Mam bibliotekę DLL C ++ innej firmy, którą wywołuję z języka C #.
Metody są statyczne.
Chcę to wyekstrahować, aby przeprowadzić testy jednostkowe, więc utworzyłem interfejs z metodami statycznymi, ale teraz mój program zawiera błędy:
Modyfikator „static” nie jest prawidłowy dla tej pozycji
MyMethod cannot be accessed with an instance reference; qualify it with a type name instead
Jak mogę osiągnąć tę abstrakcję?
Mój kod wygląda tak
private IInterfaceWithStaticMethods MyInterface;
public MyClass(IInterfaceWithStaticMethods myInterface)
{
this.MyInterface = myInterface;
}
public void MyMethod()
{
MyInterface.StaticMethod();
}
Odpowiedzi:
Nie można definiować statycznych elementów członkowskich w interfejsie w C #. Interfejs to umowa dotycząca instancji .
Zalecałbym utworzenie interfejsu tak, jak obecnie, ale bez słowa kluczowego static. Następnie utwórz klasę,
StaticIInterface
która implementuje interfejs i wywołuje statyczne metody C ++. Aby wykonać testy jednostkowe, utwórz kolejną klasęFakeIInterface
, która również implementuje interfejs, ale robi to, co jest potrzebne do obsługi testów jednostkowych.Po zdefiniowaniu tych dwóch klas możesz utworzyć taką, której potrzebujesz dla swojego środowiska, i przekazać ją do
MyClass
konstruktora.źródło
An interface is a contract, not an implementation.
- to prawda, ale tutaj zupełnie nieistotne ( non sequitur ), ponieważ metoda statyczna nie jest częścią samej implementacji - implementacja z definicji opiera się na danych , które z kolei są niedostępne dla statycznych składowych.An interface type definition can define and implement static methods (see §8.4.3) since static methods are associated with the interface type itself rather than with any value of the type.
- pamiętaj, żestatic
członkowie są zwykle metodami użytkowymi .An interface is a contract, not an implementation
jest to bezużyteczne, czasami trochę kontekstualizacji naprawdę pomaga. I całkowicie się z tym zgadzamstatic method is not a part of implementation itself
, metody statyczne mają implementację, stają się częścią implementacji tylko wtedy, gdy są używane jako implementacja w implementacji innej metody. Jednak mój słownik jest oparty na tym, czego się nauczyłem, o ile wiem, terminologia naprawdę różni się również w zależności od języka programowania. Metody statyczne nie mogą być interfejsami, ponieważ i tak może istnieć tylko 1 implementacja.IPerson
umowę, która stanowi, żeGetCountry
poda nazwę kraju pochodzenia osoby ...FrenchPerson
wszystkie podmioty będą mówić „Francja” iGermanPerson
wszystkie powiedzą „Niemcy”, co jest również przydatne, gdy różne typy podmiotów dzielą tę samą tabelę (danych), jak np. MS PowiedzmyConnection
, Azure OnePost
iComment
są przechowywane wUsers
AzureTable, więc jednostki drzewa mają wspólne informacje,IUsers
mogą miećGetTableName
metodę statyczną ...Interfejsy nie mogą mieć statycznych elementów członkowskich, a statyczne metody nie mogą być używane jako implementacja metod interfejsu.
Co możesz zrobić, to użyć jawnej implementacji interfejsu:
public interface IMyInterface { void MyMethod(); } public class MyClass : IMyInterface { static void MyMethod() { } void IMyInterface.MyMethod() { MyClass.MyMethod(); } }
Alternatywnie można po prostu użyć metod niestatycznych, nawet jeśli nie mają one dostępu do poszczególnych elementów członkowskich instancji.
źródło
Statyczne elementy członkowskie są całkowicie legalne w środowisku CLR, ale nie w języku C #.
Możesz zaimplementować trochę kleju w IL, aby połączyć szczegóły implementacji.
Nie masz pewności, czy kompilator C # pozwoliłby na ich wywoływanie?
Patrz: 8.9.4 Definicja typu interfejsu ECMA-335.
źródło
CLS Rule 19: CLS-compliant interfaces shall not define static methods, nor shall they define fields.
dalej stwierdza się, że konsumenci zgodni z CLS mogą odrzucić tego rodzaju interfejsy. Około rok temu próbowałem wywołać metodę statyczną w interfejsie, a kompilator C # nie mógł jej skompilować.Common Language Specification (CLS) is a set of basic language features that .Net Languages needed.... When there is a situation to communicate Objects written in different .Net Complaint languages , those objects must expose the features that are common to all the languages.
ma sens, że jeśli CLS dotyczy interoperacyjności między różnymi językami .NET, a C # nie zezwala na statyczne elementy członkowskie w interfejsie, to CLS również by ich zabronił, aby zapewnić biblioteki w inne języki .NET można wywoływać z poziomu C #.Można zdefiniować metody statyczne w języku C # 8, ale należy zadeklarować dla nich domyślną treść.
public interface IMyInterface { static string GetHello() => "Default Hello from interface" ; static void WriteWorld() => Console.WriteLine("Writing World from interface"); }
lub jeśli nie chcesz mieć żadnej domyślnej treści, po prostu wyrzuć wyjątek:
public interface IMyInterface { static string GetHello() => throw new NotImplementedException() ; static void WriteWorld() => throw new NotImplementedException(); }
źródło
Możesz go przywołać z refleksją:
MyInterface.GetType().InvokeMember("StaticMethod", BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, null);
źródło
C # „Dziesięć” pozwoli statycznym członkom na interfejsach , wraz z rolami. Jest to ogromny krok naprzód, który pozwoli również na przeciążenie ogólnego operatora, bez żadnej refleksji. Oto przykładowy fragment kodu, jak to działa, przy użyciu klasycznego monoidu, który jest po prostu żargonem oznaczającym „coś, co można dodać”. Zaczerpnięte bezpośrednio z 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
Dodatkowe zasoby:
Jeremy Bytes: statyczne elementy członkowskie interfejsu C # 8
EDYTOWAĆ
W tym poście pierwotnie stwierdzono, że statyczne elementy składowe interfejsu zostaną dodane w C # 8.0 , co nie jest prawdą, źle zinterpretowałem słowa Madsa Torgersena w filmie. Oficjalny przewodnik po C # 8.0 nie mówi jeszcze o statycznych elementach interfejsu, ale jest jasne, że pracowali nad tym już od dłuższego czasu.
źródło
Dlaczego nie można mieć metody statycznej na interfejsie: Dlaczego C # nie zezwala metodom statycznym na zaimplementowanie interfejsu?
Sugerowałbym jednak usunięcie metod statycznych na rzecz metod instancji. Jeśli nie jest to możliwe, można opakować wywołania metod statycznych wewnątrz metody instancji, a następnie utworzyć interfejs do tego celu i na jego podstawie uruchomić testy jednostkowe.
to znaczy
public static class MyStaticClass { public static void MyStaticMethod() {...} } public interface IStaticWrapper { void MyMethod(); } public class MyClass : IStaticWrapper { public void MyMethod() { MyStaticClass.MyStaticMethod(); } }
źródło
C # 8 umożliwia statyczne składowe w interfejsach
interfejs (odwołanie w C #)
Na przykład
public interface IGetSomething { public static string Something = "something"; } var something = IGetSomething.Something;
źródło