为什么C#接口方法不声明抽象或虚拟?

接口中的C#方法在不使用virtual关键字的情况下声明,并在派生类中重写,而不使用override关键字。

有什么原因吗?我认为它只是一种语言的方便,显然CLR知道如何处理这个覆盖(方法不是虚拟的默认),但还有其他技术原因?

下面是派生类生成的IL:

class Example : IDisposable {
    public void Dispose() { }
}

.method public hidebysig newslot virtual final 
        instance void  Dispose() cil managed
{
  // Code size       2 (0x2)
  .maxstack  8
  IL_0000:  nop
  IL_0001:  ret
} // end of method Example::Dispose

请注意,该方法在IL中声明为virtual final。

最佳答案
对于接口,添加抽象,甚至公共关键字将是多余的,所以您省略它们:

interface MyInterface {
  void Method();
}

在CIL中,该方法被标记为虚拟和抽象。

(注意,Java允许接口成员被声明为public abstract)。

对于实现类,有一些选项:

不可重写:在C#中,类不将该方法声明为虚拟。这意味着它不能在派生类(仅隐藏)中重写。在CIL中,该方法仍然是虚拟的(但是密封的),因为它必须支持关于接口类型的多态性。

class MyClass : MyInterface {
  public void Method() {}
}

可覆盖:在C#和CIL中的方法都是虚拟的。它参与多态分派,可以重写。

class MyClass : MyInterface {
  public virtual void Method() {}
}

显式:这是一个类实现接口的方法,但不提供接口方法在类本身的公共接口。在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 { }

如果Base和Derived在同一程序集中声明,编译器将使Base :: Method虚拟并密封(在CIL中),即使Base不实现接口。

如果Base和Derived在不同的程序集中,则在编译Derived程序集时,编译器不会更改其他程序集,因此将在Derived中引入一个成员,这将是MyInterface :: Method的一个显式实现,到Base :: Method。

所以你看到,每个接口方法实现必须支持多态行为,因此必须在CIL上标记为虚拟,即使编译器必须通过箍做它。

转载注明原文:为什么C#接口方法不声明抽象或虚拟? - 代码日志