对于接口,添加abstract
,甚至是public
关键字是多余的,因此您可以省略它们:
interface MyInterface {
void Method();
}
在CIL中,该方法被标记为virtual
and abstract
.
(注意Java允许声明接口成员public abstract
).
对于实现类,有一些选项:
不可重写:在 C# 中,类没有将方法声明为virtual
。这意味着它不能在派生类中被重写(只能隐藏)。在 CIL 中,该方法仍然是虚拟的(但密封的),因为它必须支持有关接口类型的多态性。
class MyClass : MyInterface {
public void Method() {}
}
可重写:在 C# 和 CIL 中,该方法都是virtual
。它参与多态调度并且可以被覆盖。
class MyClass : MyInterface {
public virtual void Method() {}
}
Explicit:这是类实现接口但不在类本身的公共接口中提供接口方法的一种方式。在 CIL 中,该方法将是private
(!) 但仍然可以从类外部通过对相应接口类型的引用来调用它。显式实现也是不可重写的。这是可能的,因为有一个 CIL 指令(.override
),它将把私有方法链接到它正在实现的相应接口方法。
[C#]
class MyClass : MyInterface {
void MyInterface.Method() {}
}
[CIL]
.method private hidebysig newslot virtual final instance void MyInterface.Method() cil managed
{
.override MyInterface::Method
}
在 VB.NET 中,您甚至可以在实现类中为接口方法名称添加别名。
[VB.NET]
Public Class MyClass
Implements MyInterface
Public Sub AliasedMethod() Implements MyInterface.Method
End Sub
End Class
[CIL]
.method public newslot virtual final instance void AliasedMethod() cil managed
{
.override MyInterface::Method
}
现在,考虑这个奇怪的情况:
interface MyInterface {
void Method();
}
class Base {
public void Method();
}
class Derived : Base, MyInterface { }
If Base
and Derived
在同一个程序集中声明,编译器将使Base::Method
虚拟和密封(在 CIL 中),即使Base
不实现该接口。
If Base
and Derived
编译时位于不同的程序集中Derived
程序集,编译器不会更改其他程序集,因此它将引入一个成员Derived
这将是一个明确的实现MyInterface::Method
这只会将调用委托给Base::Method
.
所以你看,every接口方法实现必须支持多态行为,因此必须在 CIL 上标记为 virtual,即使编译器必须经过一系列的操作才能做到这一点。