界面如何在内部工作?

时间:2014-06-15 12:02:37

标签: c#

在C#中,接口与使用纯虚函数或Java的C ++略有不同。

在接口中的C#方法中,与其他主要的编译语言不同,它不像虚拟函数,这意味着我们无法覆盖它们。

interface IMyInterface 
{
    void Foo();
}

class Root : IMyInterface 
{
    public void Foo() { ... } // OK.
}

class Child : Root
{
    public void Foo() { ... } // Not overrided.
]

所以我认为在这种情况下,界面甚至不包含vtable。

如果没有那个或任何指向函数地址的东西,C#中的接口如何在内部知道指定的调用方法在哪里?

2 个答案:

答案 0 :(得分:7)

你无法覆盖'Foo'的原因是'Root'没有将其标记为虚拟。如果将其标记为虚拟,则其工作方式与任何其他虚拟方法相同,并且可以根据需要覆盖Child。默认情况下,您可以将C#视为密封接口方法实现。好吧,事实上在C#中默认密封任何东西(当然除了终结者......)。

将此与Java等语言进行对比,其中所有实例和非私有函数默认为虚拟。

这不能回答接口如何在内部工作,但这与CLR有关,而与C#无关。基本上,CLR生成特定于接口函数的每个调用站点的代码,该代码根据对象查找它应该调用的接口函数的地址(很像普通的虚拟调度)。当然,当函数不是虚拟函数时,可以执行静态调用,如您的情况(如果我们引用ChildRoot)。

答案 1 :(得分:1)

您将接口与继承混淆..

上面示例中的

Root实现了IMyInterface并公开了IMyInterface中定义的特征。在一个完全不同的音符上Child会使所有Root的实现都进入,并且大多数都会暴露出相同特征的超集。

实际上您可以覆盖Foo中的Child,如果您使用explisit接口实现(将其命名为IMyInterface.Foo)也会重新实现

所以你可以:

    interface IMyInterface 
{
    void Foo();
}
class Root : IMyInterface 
{
    public virtual void Foo() {  } 
}

class Child : Root
{
    public override void Foo() { } 

       void IMyInterface.Foo() { } 

}

关于:

  

如果没有那个或任何指向函数地址的东西,怎么做   C#中的接口知道指定的调用方法在哪里,   内部?

你的答案在这里: http://msdn.microsoft.com/en-us/magazine/cc163791.aspx#S12 或者在推荐的书籍CLR中通过C#

重要的是要记住:.Net接口与继承无关