У меня есть сторонняя C ++ DLL, которую я вызываю из C #.
Методы статичны.
Я хочу абстрагироваться от него, чтобы провести модульное тестирование, поэтому я создал интерфейс со статическими методами в нем, но теперь мои программные ошибки:
Модификатор static недействителен для этого элемента
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
, который также реализует интерфейс, но делает то, что вам нужно для обработки ваших модульных тестов.После того как вы определили эти 2 класса, вы можете создать тот, который вам нужен для вашей среды, и передать его
MyClass
конструктору.источник
An interface is a contract, not an implementation.
- это правда, но здесь совершенно неактуально ( non sequitur ), поскольку статический метод не является частью самой реализации - реализация, по определению, основана на данных , которые, в свою очередь, недоступны для статических членов.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.
- помните, чтоstatic
члены обычно являются служебными методами .An interface is a contract, not an implementation
бесполезно, иногда немного помогает контекстуализация. И я полностью согласен с темstatic method is not a part of implementation itself
, что у статических методов есть реализация, они становятся частью реализации, только если используются в качестве реализации в реализации другого метода. Однако мой словарь основан на том, что выучил, насколько я знаю, терминология действительно меняется в зависимости от языка программирования. Статические методы не могут быть интерфейсами, потому что в любом случае может быть только одна реализация.IPerson
контракт, в котором указано, чтоGetCountry
будет указано имя страны происхождения человека ...FrenchPerson
все сущности будут говорить «Франция» иGermanPerson
все будут говорить «Германия», что также полезно, когда разные типы сущностей используют одну и ту же таблицу (данных), например MS СкажемConnection
, Azure onePost
иComment
хранятся вUsers
AzureTable, поэтому у сущностей дерева есть общая информация,IUsers
может бытьGetTableName
статический метод ...Интерфейсы не могут иметь статических членов, а статические методы не могут использоваться как реализация методов интерфейса.
Что вы можете сделать, так это использовать явную реализацию интерфейса:
public interface IMyInterface { void MyMethod(); } public class MyClass : IMyInterface { static void MyMethod() { } void IMyInterface.MyMethod() { MyClass.MyMethod(); } }
В качестве альтернативы вы можете просто использовать нестатические методы, даже если они не имеют доступа к каким-либо конкретным членам экземпляра.
источник
Статические члены совершенно допустимы в CLR, но не в C #.
Вы можете реализовать некоторый клей в IL, чтобы связать детали реализации.
Не уверены, что компилятор C # позволяет их вызывать?
См .: 8.9.4 Определение типа интерфейса ECMA-335.
источник
CLS Rule 19: CLS-compliant interfaces shall not define static methods, nor shall they define fields.
далее говорится, что CLS-совместимые потребители могут отклонить такие интерфейсы. Около года назад я пытался вызвать статический метод интерфейса, но компилятор C # не смог его скомпилировать.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.
имеет смысл, что если CLS касается взаимодействия между разными языками .NET, а C # не допускает статических членов в интерфейсе, то CLS также запретит их, чтобы библиотеки в другие языки .NET можно вызывать из C #.Вы можете определить статические методы в 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 # в будущее :
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
Дополнительные ресурсы:
Джереми Байтс: статические члены интерфейса C # 8
РЕДАКТИРОВАТЬ
В этом посте изначально заявлено, что статические элементы интерфейса будут добавлены в C # 8.0 , что неверно, я неверно истолковал слова Мадса Торгерсена в видео. Официальное руководство по 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(); } }
источник
C # 8 допускает использование статических членов в интерфейсах
интерфейс (Справочник по C #)
Например
public interface IGetSomething { public static string Something = "something"; } var something = IGetSomething.Something;
источник