Как я могу реализовать статические методы на интерфейсе? - PullRequest
68 голосов
/ 23 февраля 2012

У меня есть сторонняя 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();
}

Ответы [ 5 ]

79 голосов
/ 23 февраля 2012

Интерфейсы не могут иметь статических членов, и статические методы не могут использоваться в качестве реализации методов интерфейса.

Что вы можете сделать, это использовать явную реализацию интерфейса:

public interface IMyInterface
{
    void MyMethod();
}

public class MyClass : IMyInterface
{
    static void MyMethod()
    {
    }

    void IMyInterface.MyMethod()
    {
        MyClass.MyMethod();
    }
}

В качестве альтернативыВы можете просто использовать нестатические методы, даже если они не обращаются к каким-либо конкретным экземплярам.

37 голосов
/ 23 февраля 2012

Вы не можете определять статические члены на интерфейсе в C #. Интерфейс - это контракт для экземпляров .

Я бы порекомендовал создать интерфейс в том виде, в каком вы сейчас находитесь, но без ключевого слова static. Затем создайте класс StaticIInterface, который реализует интерфейс и вызывает статические методы C ++. Чтобы выполнить модульное тестирование, создайте другой класс FakeIInterface, который также реализует интерфейс, но делает то, что вам нужно для обработки ваших модульных тестов.

Как только вы определили эти 2 класса, вы можете создать тот, который вам нужен для вашей среды, и передать его конструктору MyClass.

15 голосов
/ 23 февраля 2012

Статические члены абсолютно легальны в CLR, только не в C #.

Вы могли бы реализовать некоторый клей в IL, чтобы связать детали реализации.

Не уверен, что компилятор C # позволит их вызывать?

См .: 8.9.4 Определение типа интерфейса ECMA-335.

Типы интерфейса обязательно неполные, так как они ничего не говорят о представлении значений типа интерфейса. За это причина, определение типа интерфейса не должно предоставлять поле определения значений типа интерфейса (т. е. полей экземпляра), хотя он может объявлять статические поля (см. §8.4.3).

Аналогично, определение типа интерфейса не должно предоставлять реализации для любых методов по значениям его типа. Тем не менее, Определение типа интерфейса может - и обычно делает - определять контракты метода (имя метода и подпись метода), который должен быть реализован вспомогательные типы. Определение типа интерфейса может определять и реализовать статические методы (см. §8.4.3), так как статические методы связано с самим типом интерфейса, а не с любым значением типа.

5 голосов
/ 23 февраля 2012

Вы можете вызвать его с отражением:

MyInterface.GetType().InvokeMember("StaticMethod", BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, null);
0 голосов
/ 23 февраля 2012

Почему у вас не может быть статического метода на интерфейсе: Почему C # не позволяет статическим методам реализовать интерфейс?

Однако я бы предложил удалить статические методыв пользу методов экземпляра.Если это невозможно, то вы можете обернуть статические вызовы метода внутри экземпляра метода, а затем вы можете создать для этого интерфейс и запустить свои модульные тесты из этого.

т.е.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...