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

Почему следующее не компилирует?

interface IFoo
{
void Foo();
}

class FooClass : IFoo
{
void IFoo.Foo() { return; }

void Another() {
   Foo();  // ERROR
 }
}

Компилятор жалуется, что "Имя 'FooMethod' не существует в текущем контексте".

Однако, если метод Foo изменяется на:

 public void Foo() { return; }

это компилирует очень хорошо.

Я не понимаю, почему каждый работает, и другой не делает.

6
задан tgiphil 27 July 2010 в 20:48
поделиться

4 ответа

Потому что, когда вы «явно реализуете» интерфейс, вы можете получить доступ к методу только путем преобразования к типу интерфейса. Неявное приведение не найдет метода.

void Another()
{
   IFoo f = (IFoo)this:
   f.Foo();
}

Дополнительная литература:

Интерфейсы C #. Неявная реализация против явной реализации

10
ответ дан 8 December 2019 в 18:30
поделиться

Попробуйте так:

void Another() {
  ((IFoo)this).Foo();
}

Поскольку вы объявляете метод Foo как явную реализацию интерфейса, вы не можете ссылаться на него в экземпляре FooClass. Вы можете ссылаться на него только путем приведения экземпляра FooClass к IFoo.

2
ответ дан 8 December 2019 в 18:30
поделиться

На самом деле существует действительно веская причина для такого поведения. Рассмотрим следующий код.

public interface IA
{
  IA DoSomething();
}

public interface IB
{
  IB DoSomething();
}

public class Test : IA, IB
{
  public IA DoSomething() { return this; }

  IA IA.DoSomething() { return this; }

  IB IB.DoSomething() { return this; }
}

В этом сценарии класс Test должен явно реализовывать по крайней мере один из методов DoSomething , поскольку незаконно объявлять два разных метода с одной и той же подписью. Если бы вы исследовали IL, вы бы увидели, что явная реализация интерфейса автоматически украшает имя члена, так что в одном классе не существует двух членов с одинаковым именем. И чтобы иметь возможность вызывать каждый из трех различных вариантов DoSomething , описанных выше, вы должны вызывать элемент из ссылки правильного типа. Вот как компилятор знает, что нужно привязаться к правильному члену.

public static void Main()
{
  var test = new Test();
  test.DoSomething(); // Compiler binds to the implicit implementation.
  var a = (IA)test;
  a.DoSomething(); // Compiler binds to the IA implementation.
  var b = (IB)test;
  b.DoSomething(); // Compiler binds to the IB implementation.
}
1
ответ дан 8 December 2019 в 18:30
поделиться

То, что у вас есть в вашем коде, называется явной реализацией интерфейса. Если вы решите поддерживать такой интерфейс, эти методы интерфейса вашего класса не будут общедоступными и могут быть вызваны только через соответствующие ссылки на типы интерфейса (IFoo в вашем примере).

0
ответ дан 8 December 2019 в 18:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: