[英]Explicit interface implementation cannot be virtual
作为记录,我已经看到了这个连接项目,但我真的不明白支持这个会有什么问题。
假设我有以下代码:
public interface IInterface
{
void Method();
}
public class Base : IInterface
{
virtual void IInterface.Method()
{
throw new NotImplementedException();
}
}
虚拟标识符有什么问题? 拥有一个虚拟修饰符可以override
表明在基础 class 中有不同的实现。 我现在可以通过删除虚拟方法并创建派生的 class 来使其工作,如下所示:
public class Derived : IInterface
{
void IInterface.Method()
{
throw new NotImplementedException();
}
}
但是这种方式我真的没有任何迹象表明我正在覆盖某些东西。
更新:
根据 C#(部分:20.4.1 显式接口成员实现)规范,有两个原因。
但是,它没有说明为什么不能使这些方法成为虚拟方法。
更新2:
鉴于答案,我认为我应该在这里重新表述真正的问题。 如果上述两个原因是首先使接口的显式实现成为可能的原因。 如果您将方法设为虚拟,为什么会有问题。
实现接口的方法显式具有特殊的可见性 scope = 除非您将“this”转换为目标接口类型,否则您无法从其他方法访问它。 我想这是不支持虚拟说明符的原因 - 您不能覆盖不属于正常 object 接口(私有/受保护/公共)的方法。
这是我的解决方法:
public class Base : IInterface
{
protected virtual void Method()
{
}
void IInterface.Method()
{
this.Method()
}
}
public class Derived : Base
{
protected override void Method()
{
}
}
但是这种方式我真的没有任何迹象表明我正在覆盖某些东西
好吧,你确实这样做了——你有一个事实,那就是它显然是一个显式的接口实现。 这表明它为在接口上指定的方法调用提供了多态行为......为什么基础 class 是否也实现了接口很重要? 当您阅读代码时,它会对您产生什么影响?
对我来说,声明override
的主要好处是确保我真的得到了正确的签名——它与我试图覆盖的东西相匹配。 您已经通过显式接口实现获得了这种好处,就好像您提供了一个不存在的方法或错误的参数等,编译器已经抱怨了。
我可以理解你的观点,但我从来没有发现它是一个实际的问题。
能够使显式接口实现成为虚拟仅在一种情况下有用:当派生类覆盖需要调用父类实现时。 不幸的是,即使可以将显式接口实现设为虚拟,也没有任何方法可以让覆盖的 class 调用其父级的实现,而没有一些新的语法来这样做。 Protected
很好地处理了这个问题,它允许实现接口的方法被声明为与接口方法不同的名称。 因此,派生的 class 可以覆盖Protected
的方法(使用适当的名称),并且该覆盖可以调用父类版本(使用相同的名称)。
如果只有一个接口被继承,为什么需要这样做:
public class Base : IInterface
{
virtual void IInterface.Method()
{
throw new NotImplementedException();
}
}
为什么不只是 go:
public class Base : IInterface
{
virtual void Method()
{
throw new NotImplementedException();
}
}
我认为原因可以简单地显示在以下示例中。 考虑这段代码:
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???
}
}
因此,简而言之,如果您使用相同的方法签名显式实现多个接口,您的派生类将不知道您要覆盖哪个基方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.