Почему метод с префиксом имени интерфейса не компилируется в C #? - PullRequest
6 голосов
/ 28 июля 2010

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

interface IFoo
{
void Foo();
}

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

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

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

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

 public void Foo() { return; }

, это компилируется просто отлично.

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

Ответы [ 4 ]

10 голосов
/ 28 июля 2010

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

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

Дополнительная информация:

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

2 голосов
/ 28 июля 2010

Попробуйте это:

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

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

1 голос
/ 28 июля 2010

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

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, вы бы увидели, что явная реализация интерфейса украшает имя члена автоматически, так что в одном и том же классе не существует двух членов с одинаковым именем.И чтобы иметь возможность вызывать каждую из 3 различных 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.
}
0 голосов
/ 28 июля 2010

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

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