繁体   English   中英

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

[英]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 显式接口成员实现)规范,有两个原因。

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

但是,它没有说明为什么不能使这些方法成为虚拟方法。

更新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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM