C #에서 호출하는 타사 C ++ DLL이 있습니다.
메서드는 정적입니다.
일부 단위 테스트를 수행하기 위해 추상화하고 싶으므로 정적 메서드로 인터페이스를 만들었지 만 이제 프로그램 오류는 다음과 같습니다.
수정 자 ‘정적’은이 항목에 유효하지 않습니다.
MyMethod cannot be accessed with an instance reference; qualify it with a type name instead
이 추상화를 어떻게 얻을 수 있습니까?
내 코드는 다음과 같습니다.
private IInterfaceWithStaticMethods MyInterface;
public MyClass(IInterfaceWithStaticMethods myInterface)
{
this.MyInterface = myInterface;
}
public void MyMethod()
{
MyInterface.StaticMethod();
}
답변
C #의 인터페이스에는 정적 멤버를 정의 할 수 없습니다. 인터페이스는 인스턴스에 대한 계약 입니다 .
현재 상태 그대로 인터페이스를 만드는 것이 좋지만 static 키워드는 사용하지 않는 것이 좋습니다. 그런 다음 StaticIInterface
인터페이스를 구현하고 정적 C ++ 메서드를 호출 하는 클래스 를 만듭니다 . 단위 테스트를 수행하려면 FakeIInterface
인터페이스도 구현하지만 단위 테스트를 처리하는 데 필요한 작업을 수행하는 다른 클래스를 만듭니다 .
이 두 가지 클래스를 정의한 후에는 환경에 필요한 클래스를 만들고 MyClass
의 생성자에 전달할 수 있습니다.
답변
인터페이스는 정적 멤버를 가질 수 없으며 정적 메서드는 인터페이스 메서드의 구현으로 사용할 수 없습니다.
할 수있는 일은 명시 적 인터페이스 구현을 사용하는 것입니다.
public interface IMyInterface
{
void MyMethod();
}
public class MyClass : IMyInterface
{
static void MyMethod()
{
}
void IMyInterface.MyMethod()
{
MyClass.MyMethod();
}
}
또는 인스턴스 특정 멤버에 액세스하지 않더라도 비 정적 메서드를 사용할 수 있습니다.
답변
정적 멤버는 C #이 아닌 CLR에서 완벽하게 합법적입니다.
IL에서 접착제를 구현하여 구현 세부 정보를 연결할 수 있습니다.
C # 컴파일러가 호출을 허용하는지 확실하지 않습니까?
참조 : 8.9.4 인터페이스 유형 정의 ECMA-335.
인터페이스 유형은 인터페이스 유형 값의 표현에 대해 아무 말도하지 않기 때문에 반드시 불완전합니다. 이러한 이유로 인터페이스 유형 정의는 정적 필드를 선언 할 수 있지만 (§8.4.3 참조) 인터페이스 유형의 값 (즉, 인스턴스 필드)에 대한 필드 정의를 제공해서는 안됩니다.
유사하게, 인터페이스 유형 정의는 그 유형의 값에 대한 메소드에 대한 구현을 제공하지 않아야합니다. 그러나 인터페이스 유형 정의는 지원 유형에 의해 구현되어야하는 메소드 계약 (메서드 이름 및 메소드 서명)을 정의 할 수 있으며 일반적으로 정의합니다. 인터페이스 형식 정의는 정적 메서드 (§8.4.3 참조)를 정의하고 구현할 수 있습니다. 정적 메서드는 형식의 값이 아닌 인터페이스 형식 자체와 연결되기 때문입니다.
답변
C # 8에서 정적 메서드를 정의 할 수 있지만 이에 대한 기본 본문을 선언해야합니다.
public interface IMyInterface
{
static string GetHello() => "Default Hello from interface" ;
static void WriteWorld() => Console.WriteLine("Writing World from interface");
}
또는 기본 본문을 원하지 않는 경우 예외를 발생시킵니다.
public interface IMyInterface
{
static string GetHello() => throw new NotImplementedException() ;
static void WriteWorld() => throw new NotImplementedException();
}
답변
리플렉션을 사용하여 호출 할 수 있습니다.
MyInterface.GetType().InvokeMember("StaticMethod", BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, null);
답변
C # “Ten”은 역할과 함께 인터페이스 에서 정적 멤버를 허용 합니다. 이것은 큰 진전이며, 리플렉션을 사용하지 않고 일반 연산자 오버로딩도 허용합니다. 다음은 “추가 할 수있는 것”을 말하는 전문 용어 인 고전적인 모노 이드 예제를 사용하여 작동 방식의 예제 스 니펫입니다. Mads Torgersen 에서 직접 발췌 : C # into the Future :
interface IMonoid<T>
{
static T Zero { get; }
static T operator +(T t1, T t2);
}
public static T AddAll<T>(T[] ts) where T : IMonoid<T>
{
T result = T.Zero;
foreach (T t in ts) { result += t; }
return result;
}
role IntAddMonoid extends int : IMonoid<int>
{
public static int Zero => 0;
}
IntAddMonoid[] values = new int[] {1, 2, 4, 8, 16, 32};
int sixtyThree = AddAll<IntAddMonoid>(values); // == 63
추가 리소스 :
Jeremy Bytes : C # 8 인터페이스 정적 멤버
편집하다
이 게시물은 원래 인터페이스 정적 멤버가 C # 8.0에 추가 될 것이라고 언급 했는데 이는 사실이 아닙니다. 비디오에서 Mads Torgersen의 말을 잘못 해석했습니다. 공식 C # 8.0 가이드 는 아직 정적 인터페이스 멤버에 대해 이야기하지 않지만, 지금까지 꽤 오랫동안 작업 해 왔음이 분명합니다.
답변
인터페이스에 정적 메서드를 사용할 수없는 이유 : C #에서 정적 메서드가 인터페이스를 구현하도록 허용하지 않는 이유는 무엇입니까?
그러나 인스턴스 메서드를 선호하는 정적 메서드를 제거하는 것이 좋습니다. 가능하지 않은 경우 인스턴스 메서드 내부에 정적 메서드 호출을 래핑 한 다음 해당 인터페이스를 만들고 여기에서 단위 테스트를 실행할 수 있습니다.
즉
public static class MyStaticClass
{
public static void MyStaticMethod()
{...}
}
public interface IStaticWrapper
{
void MyMethod();
}
public class MyClass : IStaticWrapper
{
public void MyMethod()
{
MyStaticClass.MyStaticMethod();
}
}