代码之家  ›  专栏  ›  技术社区  ›  tgiphil

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

  •  6
  • tgiphil  · 技术社区  · 14 年前

    为什么不编译以下内容?

    interface IFoo
    {
    void Foo();
    }
    
    class FooClass : IFoo
    {
    void IFoo.Foo() { return; }
    
    void Another() {
       Foo();  // ERROR
     }
    }
    

    编译器抱怨“当前上下文中不存在名称‘foomethod’”。

    但是,如果foo方法更改为:

     public void Foo() { return; }
    

    这编译得很好。

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

    4 回复  |  直到 14 年前
        1
  •  10
  •   Community CDub    8 年前

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

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

    进一步阅读:

    C# Interfaces. Implicit implementation versus Explicit implementation

        2
  •  2
  •   John Bledsoe    14 年前

    试试这个:

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

    因为您将foo方法声明为 explicit interface implementation ,不能在fooclass实例上引用它。您只能通过将fooclass的实例强制转换为ifoo来引用它。

        3
  •  1
  •   Brian Gideon    14 年前

    事实上,这种行为有很好的理由。考虑下面的代码。

    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,您将看到显式实现接口会自动修饰成员名称,从而使同一类中不存在具有相同名称的两个成员。并且能够调用三个不同的 剂量测定法 上面的变体必须从正确类型的引用中调用成员。这就是编译器知道如何绑定到正确的成员。

    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.
    }
    
        4
  •  0
  •   Alan    14 年前

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