显式接口实现不能是虚拟的

为了记录,我已经看过这个连接项,但我真的不明白支持这个问题会是什么。

说我有以下代码:

public interface IInterface { void Method(); } public class Base : IInterface { virtual void IInterface.Method() { throw new NotImplementedException(); } } 

虚拟标识符有什么问题? 拥有虚拟修饰符可以override指示基类中有不同的实现。 我现在可以通过删除虚方法并创建如下的派生类来使其工作:

 public class Derived : IInterface { void IInterface.Method() { throw new NotImplementedException(); } } 

但是这样我真的没有迹象表明我压倒了什么。

更新:
根据C#(部分:20.4.1显式接口成员实现)规范,有两个原因。

  1. 隐藏某些方法(我正在使用它)。
  2. 具有相同签名但具有不同返回类型的2个函数(例如,对IClonable有用)。

它没有说明为什么你不能使这些方法虚拟。

UPDATE2:
鉴于答案,我认为我应该在这里重新提出真正的问题。 如果以上两个原因是首先使接口的显式实现成为可能的原因。 如果将方法设为虚拟,为什么会出现问题?

但是这样我真的没有迹象表明我压倒了什么

嗯,你这样做 – 你有一个事实,它显然是一个明确的接口实现。 这表明它为在接口上指定的方法调用提供了多态行为…为什么基类是否实现了接口? 阅读代码时,它会给你带来什么不同?

对我来说,说明override的主要好处是确保我确实得到了正确的签名 – 它与我试图覆盖的东西相匹配。 您已经通过显式接口实现获得了这样的好处,就好像您提供了一个不存在的方法或错误的参数等,编译器已经会抱怨。

我可以看到你的观点,但我从来没有发现它是一个实际的问题。

显式实现接口的方法具有特殊的可见范围=除非将“this”转换为目标接口类型,否则无法从其他方法访问它。 我想这就是为什么不支持虚拟说明符的原因 – 你不能覆盖不属于普通对象接口(private / protected / public)的方法。

这是我的解决方法:

 public class Base : IInterface { protected virtual void Method() { } void IInterface.Method() { this.Method() } } public class Derived : Base { protected override void Method() { } } 

如果只有一个inheritance的接口,为什么需要这样做:

 public class Base : IInterface { virtual void IInterface.Method() { throw new NotImplementedException(); } } 

为什么不去:

 public class Base : IInterface { virtual void Method() { throw new NotImplementedException(); } } 

能够将显式接口实现为虚拟化仅在一种情况下有用:当派生类覆盖需要调用父类实现时。 不幸的是,即使显式接口实现可以变为虚拟,也不会有任何方法让覆盖类调用其父实现,而没有这样做的新语法。 VB.net通过允许实现接口的方法声明Protected ,使用与接口方法不同的名称来处理这个问题。 因此派生类可以覆盖Protected方法(使用适当的名称),并且该覆盖可以调用父类版本(使用相同的名称)。

我认为原因可以在下面的例子中简单地显示出来。 考虑以下代码:

 public interface IInterfaceA { void Method(); } public interface IInterfaceB { void Method(); } public class Base : IInterfaceA, IInterfaceB { virtual void IInterfaceA.Method() { ... } virtual void IInterfaceB.Method() { ... } } public class Derived : Base { public override void Method() { // Will this override IInterfaceA or IInterfaceB implementation??? } } 

因此,简而言之,如果您使用相同的方法签名显式实现多个接口,则派生类将不知道您要覆盖哪个基本方法。