17

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

假设我有以下代码:

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:
鉴于答案,我认为我应该在这里重新表述真正的问题。如果上述两个原因是首先使接口的显式实现成为可能的原因。如果您将方法设为虚拟,为什么会有问题。

4

5 回答 5

16

实现接口的方法显式具有特殊的可见性范围=除非您将“this”强制转换为目标接口类型,否则您无法从其他方法访问它。我想这是不支持虚拟说明符的原因 - 您不能覆盖不属于普通对象接口(私有/受保护/公共)的方法。

这是我的解决方法:

public class Base : IInterface
{    
   protected virtual void Method()
   {

   }

   void IInterface.Method()    
   {        
       this.Method()
   }
 }


 public class Derived : Base
 {
     protected override void Method()
     {
     }
 }
于 2011-08-17T09:04:47.410 回答
7

但是这种方式我真的没有任何迹象表明我正在覆盖某些东西

好吧,你确实这样做了——你有一个事实,那就是它显然是一个显式的接口实现。这表明它为在接口上指定的方法调用提供了多态行为......为什么基类是否实现了接口很重要?当您阅读代码时,它会对您产生什么影响?

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

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

于 2011-08-17T08:58:45.057 回答
0

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

于 2012-09-13T23:11:03.253 回答
-1

我认为原因可以简单地显示在以下示例中。考虑这段代码:

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

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

于 2013-04-04T03:22:54.990 回答
-1

如果只有一个接口被继承,为什么需要这样做:

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

为什么不去:

public class Base : IInterface
{
   virtual void Method()
   {
      throw new NotImplementedException();
   }
}
于 2011-08-17T08:57:05.427 回答