为什么以接口名为前缀的方法不能在C#中编译?

时间:2010-07-27 20:48:35

标签: c# interface

为什么以下不能编译?

interface IFoo
{
void Foo();
}

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

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

编译器抱怨“当前上下文中不存在名称'FooMethod'”。

但是,如果将Foo方法更改为:

 public void Foo() { return; }

这个编译得很好。

我不明白为什么一个有效,另一个没有。

4 个答案:

答案 0 :(得分:10)

因为当您“显式实现”接口时,您只能通过强制转换为接口类型来访问该方法。隐式投射将找不到该方法。

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

进一步阅读:

C# Interfaces. Implicit implementation versus Explicit implementation

答案 1 :(得分:2)

试试这个:

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

由于您将Foo方法声明为explicit interface implementation,因此无法在FooClass的实例上引用它。您只能通过将FooClass的实例强制转换为IFoo来引用它。

答案 2 :(得分:1)

这种行为确实有很好的理由。请考虑以下代码。

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.
}

答案 3 :(得分:0)

您的代码中包含的内容称为显式接口实现。如果你选择支持这样的接口,你的类的这些接口方法不是公共的,只能通过适当的接口类型引用调用(在你的例子中是IFoo)。