为什么 C# 接口方法没有声明为抽象或虚拟? [英] Why are C# interface methods not declared abstract or virtual?

查看:26
本文介绍了为什么 C# 接口方法没有声明为抽象或虚拟?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

接口中的 C# 方法不使用 virtual 关键字声明,并在派生类中覆盖而不使用 override 关键字.

C# methods in interfaces are declared without using the virtual keyword, and overridden in the derived class without using the override keyword.

这是有原因的吗?我认为这只是一种语言方便,显然 CLR 知道如何在幕后处理这个问题(默认情况下方法不是虚拟的),但还有其他技术原因吗?

Is there a reason for this? I assume that it is just a language convenience, and obviously the CLR knows how to handle this under the covers (methods are not virtual by default), but are there other technical reasons?

这是派生类生成的 IL:

Here is the IL that a derived class generates:

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.

Notice that the method is declared virtual final in the IL.

推荐答案

对于界面来说,添加abstract,甚至public关键字都是多余的,所以你省略了它们:

For the interface, the addition of the abstract, or even the public keywords would be redundant, so you omit them:

interface MyInterface {
  void Method();
}

在CIL中,方法被标记为virtualabstract.

In the CIL, the method is marked virtual and abstract.

(注意 Java 允许将接口成员声明为 public abstract).

(Note that Java allows interface members to be declared public abstract).

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

For the implementing class, there are some options:

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

Non-overridable: In C# the class doesn't declare the method as virtual. That means that it cannot be overridden in a derived class (only hidden). In the CIL the method is still virtual (but sealed) because it must support polymorphism regarding the interface type.

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

Overridable:在 C# 和 CIL 中,该方法都是virtual.它参与多态调度并且可以被覆盖.

Overridable: Both in C# and in the CIL the method is virtual. It participates in polymorphic dispatch and it can be overridden.

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

Explicit:这是一个类实现一个接口但不提供该类本身的公共接口中的接口方法的一种方式.在 CIL 中,该方法将是 private (!) 但它仍然可以从类外部通过对相应接口类型的引用调用.显式实现也是不可覆盖的.这是可能的,因为有一个 CIL 指令 (.override) 将私有方法链接到它正在实现的相应接口方法.

Explicit: This is a way for a class to implement an interface but not provide the interface methods in the public interface of the class itself. In the CIL the method will be private (!) but it will still be callable from outside the class from a reference to the corresponding interface type. Explicit implementations are also non-overridable. This is possible because there's a CIL directive (.override) that will link the private method to the corresponding interface method that it's implementing.

[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 中,您甚至可以在实现类中为接口方法名称取别名.

In VB.NET, you can even alias the interface method name in the implementing class.

[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
}

现在,考虑这个奇怪的案例:

Now, consider this weird case:

interface MyInterface {
  void Method();
}
class Base {
  public void Method();
}
class Derived : Base, MyInterface { }

如果 BaseDerived 在同一个程序集中声明,编译器将使 Base::Method 虚拟和密封(在 CIL),即使 Base 没有实现接口.

If Base and Derived are declared in the same assembly, the compiler will make Base::Method virtual and sealed (in the CIL), even though Base doesn't implement the interface.

如果BaseDerived在不同的程序集中,编译Derived程序集时,编译器不会改变其他程序集,所以它将在 Derived 中引入一个成员,该成员将是 MyInterface::Method 的显式实现,它将调用委托给 Base::Method.

If Base and Derived are in different assemblies, when compiling the Derived assembly, the compiler won't change the other assembly, so it will introduce a member in Derived that will be an explicit implementation for MyInterface::Method that will just delegate the call to Base::Method.

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

So you see, every interface method implementation must support polymorphic behavior, and thus must be marked virtual on the CIL, even if the compiler must go through hoops to do it.

这篇关于为什么 C# 接口方法没有声明为抽象或虚拟?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆