Код Visual Studio генерируется при выборе явной реализации интерфейса - PullRequest
1 голос
/ 03 июня 2010

Извините за смутное название, но я не уверен, как это называется.

Допустим, я добавил IDisposable в свой класс, Visual Studio может создать для меня заглушку метода. Но это создает заглушку, как:

void IDisposable.Dispose()

Я не понимаю, что делает этот синтаксис. Почему так вместо public void Dispose()?

И с первым синтаксисом я не мог понять, как вызвать Dispose () из моего класса (в моем деструкторе).

Ответы [ 3 ]

2 голосов
/ 03 июня 2010

Когда вы явно реализуете элемент интерфейса, что и делает сгенерированный код, вы не можете получить доступ к члену через экземпляр класса. Вместо этого вы должны вызвать его через экземпляр интерфейса. Например:

class MyClass : IDisposable
{
  void IDisposable.Dispose()
  {
    // Do Stuff
  }

  ~MyClass()
  {
    IDisposable me = (IDisposable)this;
    me.Dispose();
  }
}

Это позволяет вам реализовать два интерфейса с одним и тем же членом и явно вызывать любой из них независимо.

interface IExplict1 
{
  string InterfaceName();
}

interface IExplict2
{
  string InterfaceName();
}

class MyClass : IExplict1, IExplict2 
{
  string IExplict1.InterfaceName() 
  {
    return "IExplicit1";
  }

  string IExplict2.InterfaceName() 
  {
    return "IExplicit2";
  }
}

public static void Main() 
{
  MyClass myInstance = new MyClass();

  Console.WriteLine( ((IExplcit1)myInstance).InstanceName() ); // outputs "IExplicit1"

  IExplicit2 myExplicit2Instance = (IExplicit2)myInstance;

  Console.WriteLine( myExplicit2Instance.InstanceName() ); // outputs "IExplicit2"
}
1 голос
/ 03 июня 2010

Члены типа интерфейса всегда общедоступны. Что требует, чтобы реализация их метода была публичной. Это не компилируется, например:

interface IFoo { void Bar(); }

class Baz : IFoo {
    private void Bar() { }   // CS0737
}

Явная реализация интерфейса предоставляет синтаксис, который позволяет методу быть закрытым:

class Baz : IFoo {
    void IFoo.Bar() { }   // No error
}

Классическое использование для этого - скрыть реализацию базового типа интерфейса. IEnumerable <> был бы очень хорошим примером:

class Baz : IEnumerable<Foo> {
    public IEnumerator<Foo> GetEnumerator() {}
    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { }
}

Обратите внимание, как доступна универсальная версия, неуниверсальная версия скрыта. Это препятствует его использованию и позволяет избежать ошибки компиляции из-за дублированного метода.


В вашем случае реализация Dispose () явно неверна. Вы написали Dispose (), чтобы позволить клиентскому коду вызывать его, заставляя приводить его к IDisposable, чтобы сделать вызов не имеет смысла.

Кроме того, вызов Dispose () из финализатора является запахом кода. Стандартный шаблон - добавить в ваш класс защищенный метод Dispose (удаление в bool).

1 голос
/ 03 июня 2010

Visual studio предоставляет вам два варианта:

  • Реализовать
  • Реализовать явно

Обычно вы выбираете первый (неявный): который дает вам поведение, которое вы хотите.

Опция "явный" полезна, если вы наследуете один и тот же метод от двух разных интерфейсов, т.е. множественное наследование (что обычно не происходит).

...