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

时间:2011-08-17 08:52:43

标签: c# compiler-construction interface explicit-interface

为了记录,我已经看过这个connect item,但我不能真正理解支持这个问题会是什么。

说我有以下代码:

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有用)。
  3. 但是没有说明为什么你不能将这些方法虚拟化。

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

5 个答案:

答案 0 :(得分:14)

实现接口的方法显式具有特殊的可见范围=除非将“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()
     {
     }
 }

答案 1 :(得分:7)

  然而,这种方式我根本没有迹象表明我压倒了什么

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

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

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

答案 2 :(得分:0)

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

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

为什么不去:

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

答案 3 :(得分:0)

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

答案 4 :(得分:-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???
    }
}

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