Почему следующее не компилирует?
interface IFoo
{
void Foo();
}
class FooClass : IFoo
{
void IFoo.Foo() { return; }
void Another() {
Foo(); // ERROR
}
}
Компилятор жалуется, что "Имя 'FooMethod' не существует в текущем контексте".
Однако, если метод Foo изменяется на:
public void Foo() { return; }
это компилирует очень хорошо.
Я не понимаю, почему каждый работает, и другой не делает.
Потому что, когда вы «явно реализуете» интерфейс, вы можете получить доступ к методу только путем преобразования к типу интерфейса. Неявное приведение не найдет метода.
void Another()
{
IFoo f = (IFoo)this:
f.Foo();
}
Дополнительная литература:
Попробуйте так:
void Another() {
((IFoo)this).Foo();
}
Поскольку вы объявляете метод Foo как явную реализацию интерфейса, вы не можете ссылаться на него в экземпляре FooClass. Вы можете ссылаться на него только путем приведения экземпляра FooClass к IFoo.
На самом деле существует действительно веская причина для такого поведения. Рассмотрим следующий код.
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.
}
То, что у вас есть в вашем коде, называется явной реализацией интерфейса. Если вы решите поддерживать такой интерфейс, эти методы интерфейса вашего класса не будут общедоступными и могут быть вызваны только через соответствующие ссылки на типы интерфейса (IFoo в вашем примере).