【问题标题】:Difference between implicit and explicit implementation of C# interfaces [duplicate]C#接口的隐式和显式实现之间的区别[重复]
【发布时间】:2010-10-17 07:02:39
【问题描述】:

显式实现接口实现接口有什么区别。

当您从接口派生类时,intellisense 建议您两者都做。

但是,有什么区别呢?

【问题讨论】:

    标签: c# interface


    【解决方案1】:

    另一方面:

    如果您隐式实现,则意味着您的类的用户可以访问接口成员,而无需他们进行强制转换。

    如果它是显式实现的,则客户端必须先将您的类转换为接口,然后才能访问成员。 下面是一个显式实现的例子:

        interface Animal
    {
        void EatRoots();
        void EatLeaves();
    }
    
    interface Animal2
    {
        void Sleep();
    }
    
    
    class Wombat : Animal, Animal2
    {
        // Implicit implementation of Animal2
        public void Sleep()
        {
        }
    
        // Explicit implementation of Animal
        void Animal.EatRoots()
        {
    
        }
    
        void Animal.EatLeaves()
        {
        }
    
    }
    

    您的客户代码

    Wombat w = new Wombat();
    w.Sleep();
    w.EatRoots();   // This will cause a compiler error because it's explicitly implemented
    ((Animal)w).EatRoots();  // This will compile
    

    【讨论】:

      【解决方案2】:

      IDE 为您提供了 选项 来做任何一个 - 两者都做是不寻常的。通过显式实现,成员不在(主要)公共 API 上;如果接口不直接与对象的意图相关联,这很方便。例如,ICustomTypeDescriptor 成员对普通调用者并没有太大帮助 - 仅对一些非常具体的代码有帮助,因此将它们放在公共 API 上造成混乱是没有意义的。

      这在以下情况下也很有用:

      • 接口的Foo 方法和您自己类型的Foo 方法之间存在冲突,它们的含义不同
      • 其他接口之间存在签名冲突

      最后一点的典型例子是IEnumerable<T>,它在接口层次结构的两个层次上都有一个GetEnumerator()方法——常见的是使用隐式实现来实现类型化的(IEnumerator<T>)版本,而非类型化的(IEnumerator) 版本使用显式实现。

      【讨论】:

      • 当您的类需要实现您不想从程序集中公开导出的内部接口时,显式实现也很有用。
      【解决方案3】:

      这是简单英语的区别:

      假设你有一个接口Machine,它有一个函数Run(),另一个接口Animal也有一个函数Run()。当然,当机器运行时,我们谈论的是它的启动,但是当动物奔跑时,我们谈论的是它四处移动。那么当你有一个对象时会发生什么,我们称它为Aibo,它既是Machine,又是Animal? (顺便说一句,Aibo 是一只机械狗。)Aibo 跑步时,他是启动还是四处走动?显式实现一个接口可以让您做出区分:

      interface Animal
      {
          void Run();
      }
      interface Machine
      {
          void Run();
      }
      
      class Aibo : Animal, Machine
      {
          void Animal.Run()
          {
              System.Console.WriteLine("Aibo goes for a run.");
          }
          void Machine.Run()
          {
              System.Console.WriteLine("Aibo starting up.");
          }
      }
      class Program
      {
          static void Main(string[] args)
          {
              Aibo a = new Aibo();
              ((Machine)a).Run();
              ((Animal)a).Run();
          }
      }
      

      这里的问题是我不能简单地调用a.Run(),因为我的两个函数实现都显式附加到一个接口。这是有道理的,否则编译器怎么知道该调用哪一个呢?相反,如果我想直接在 Aibo 上调用 Run() 函数,我将不得不在没有显式接口的情况下实现该函数。

      【讨论】:

        【解决方案4】:

        显式将IInterfaceName。在所有接口实现的前面。如果您需要实现两个包含冲突的名称/签名的接口,这将非常有用。

        更多信息here.

        【讨论】:

          【解决方案5】:

          显式实现将完全限定名称放在函数名上考虑此代码

              public interface IamSam
              {
                  int foo();
                  void bar();
              }
          
              public class SamExplicit : IamSam
              {
                  #region IamSam Members
          
                  int IamSam.foo()
                  {
                      return 0;
                  }
          
                  void IamSam.bar()
                  {
          
                  }
          
                  string foo()
                  {
                      return "";
                  }
                  #endregion
              }
          
              public class Sam : IamSam
              {
                  #region IamSam Members
          
                  public int foo()
                  {
                      return 0;
                  }
          
                  public void bar()
                  {
          
                  }
          
                  #endregion
              }
          
          IamSam var1;
          var1.foo()  returns an int.
          SamExplicit var2;
          var2.foo() returns a string.
          (var2 as IamSam).foo() returns an int.
          

          【讨论】:

            【解决方案6】:

            给你,直接来自MSDN

            【讨论】:

              【解决方案7】:

              不同之处在于您可以从多个接口继承一个类。这些接口可能具有相同的方法签名。显式实现允许您根据调用它的接口来更改您的实现。

              【讨论】:

                【解决方案8】:

                显式接口实现,除非您显式强制转换,否则该实现是隐藏的,当接口与类功能正交时最有用。也就是说,行为上不相关。

                例如,如果您的类是 Person 并且接口是 ISerializable,那么处理 Person 属性的人通过 Intellisense 看到名为“GetObjectData”的奇怪东西就没有多大意义。因此,您可能希望显式实现该接口。

                另一方面,如果您的 person 类碰巧实现了 IAddress,那么直接在 Person 实例上查看 AddressLine1、ZipCode 等成员(隐式实现)非常有意义。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2010-10-10
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2012-11-04
                  • 1970-01-01
                  相关资源
                  最近更新 更多