【问题标题】:Why am I getting an error in C# when mixing explicit implementation and polymorphism?为什么在混合显式实现和多态时在 C# 中出现错误?
【发布时间】:2010-10-17 04:40:52
【问题描述】:

我收到此错误:

type Bar 没有实现接口 IFoo

从此代码:

public interface IFoo
{
   void DoA();

   void DoB();
}

public class Foo:IFoo
{

    void IFoo.DoA()
    {

    }

    void IFoo.DoB()
    {


   }
}

public class Bar:Foo
{

     void IFoo.DoA()
      {
          base.doA();

      }

      void IFoo.DoB()
      {
          base.doB();

      }
  }  

我正在使用 C# 2.0。

我做错了什么?

【问题讨论】:

    标签: c# .net design-patterns


    【解决方案1】:
    public class Bar : Foo, IFoo
    { 
        // Your code
    }
    

    【讨论】:

    • 为什么需要 IFoo?为什么是-1?
    • 我猜是-1,因为人们认为它很明显...通过添加 IFoo,您说 Bar 有自己的实现,与 Foo 的实现不同。这就是它明确的意义所在。 Foo 的明确实现与 Foo 保持一致。
    【解决方案2】:

    我也遇到过这种情况。什么是“更糟糕”,取决于你如何看待它,你不能将接口实现定义为虚拟的,以便在后代类中被覆盖。我已经养成了这样做的习惯:

    public class Foo:IFoo
    {    
         void IFoo.DoA()
         {
              DoACore();
         }
         void IFoo.DoB()
         {
              DoBCore();
         }
         protected virtual void DoACore()
         {
         }
         protected virtual void DoBCore()
         {
         }
    }
    public class Bar:Foo
    {     protected override void DoACore()
          {
              base.DoACore();
          }
          protected override void DoBCore()
          {
              base.DoBCore();
          }
    }
    

    【讨论】:

    • +1,你应该接受这个答案。这是 .Net 中用于处理深度继承树中的接口实现的“标准”实践。
    • 绝对......我喜欢这个解决方案......迈克尔你和n8wrl是同一个人吗,试着获得投票:)?
    • 覆盖方法的命名约定是什么?
    • 取决于您在哪里工作。在 WinForms 中,它是 On[method],但它变得丑陋,因为 On[Method] 也可以用于事件。只需选择一个适合您并保持一致的约定即可。
    • 那么为什么不简单地使用隐式实现呢?声明 DoA、DoB 虚拟,你就完成了。或者你有一些这里没有提到的目标?
    【解决方案3】:

    请参阅n8wrl's answer,了解您应该如何执行此操作。原因见下文。

    当隐式实现接口时,您不能显式实现接口成员 (void IFoo.DoA())。换句话说,因为 Bar 通过扩展Foo 只实现了IFoo,所以不能使用显式实现。

    这将起作用:

    public class Bar : Foo
    {
        public void DoA()
        {
            ...
        }
    
        public void DoB()
        {
            ...
        }
    

    或者这个:

    public class Bar : Foo, IFoo
    {
        void IFoo.DoA()
        {
            ...
        }
    
        void IFoo.DoB()
        {
            ...
        }
    

    您可能会面临一个更大的问题是,由于Foo 不是抽象的,它必须实现DoADoB。如果您在 bar 中实现这些方法,您将不会以多态方式执行它。如果代码具有Bar 类型的句柄,您将成为hidingFoo 实现。

    【讨论】:

    • 对,这就是我评论它的原因。这是一个单独的问题。首先,在 base 中没有 doA 的实现,其次,如果您指的是 DoA,因为它是显式实现的,除非您将 base 转换为 IFoo,否则它是不可见的......
    • 如果你将 base 转换为 IFoo,它是不可见的,因为编译器无法确定使用哪个 IFoo(因为两个类都实现了 IFoo,正如我在答案中所说,它不是多态的。class="comcopy">Efen跨度>
    【解决方案4】:

    我怀疑接口是如何在 C++ 中作为抽象类和多重继承实现的。

    在 .NET 中,接口只是表示您将实现这些方法的合同。

    您的代码无法编译,原因与此代码无法编译的原因相同(使用 C++ 编译):

    public interface IFoo
    {
        void DoSomething();
    }
    
    public abstract class Foo : IFoo
    {
    }
    

    Foo 声明 Foo 实现了 IFoo,它没有说明任何人。

    如果你想强制派生类实现它,你会这样做:

    public interface IFoo
    {
        void DoSomething();
    }
    
    public abstract class Foo : IFoo
    {
        public abstract void DoSomething();
    }
    

    或者,如果您真的希望通过显式实现隐藏接口方法,则可以使用上面发布的 n8wrl 之类的东西。

    【讨论】:

    • 抱歉,您这么认为...我认为您遇到的问题是 .NET 中的接口方法不像 C++ 中那样自动虚拟。
    【解决方案5】:

    起初,不清楚这是什么任务?如果目标是尽快解决问题,那么“Bar : Foo, IFoo”是最短的解决方案。

    如果您只是想了解“隐式/显式”接口的区别,请查看post

    另请注意,“n8wrl”解决方案是有争议的。仅当 Foo 确实需要显式实现 IFoo 时才可以。如果没有,比有一个更简单的方法:

    public interface IFoo
    {
        void DoA();
    }
    
    public class Foo : IFoo
    {
        public virtual void DoA() {}
    }
    
    public class Bar : Foo
    {
        public override void DoA() {}
    }
    

    希望这会有所帮助。

    【讨论】:

    • @Sasha,我刚刚注意到建议的帖子是你的问题:-)
    猜你喜欢
    • 2018-01-05
    • 1970-01-01
    • 1970-01-01
    • 2011-10-11
    • 1970-01-01
    • 2012-08-13
    • 2023-01-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多