在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#中的接口如何在内部知道指定的调用方法在哪里?
答案 0 :(得分:7)
你无法覆盖'Foo'的原因是'Root'没有将其标记为虚拟。如果将其标记为虚拟,则其工作方式与任何其他虚拟方法相同,并且可以根据需要覆盖Child。默认情况下,您可以将C#视为密封接口方法实现。好吧,事实上在C#中默认密封任何东西(当然除了终结者......)。
将此与Java等语言进行对比,其中所有实例和非私有函数默认为虚拟。
这不能回答接口如何在内部工作,但这与CLR有关,而与C#无关。基本上,CLR生成特定于接口函数的每个调用站点的代码,该代码根据对象查找它应该调用的接口函数的地址(很像普通的虚拟调度)。当然,当函数不是虚拟函数时,可以执行静态调用,如您的情况(如果我们引用Child
或Root
)。
答案 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接口与继承无关