C#接口的隐式和显式实现之间的区别[重复]

Posted

技术标签:

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

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

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

但是,有什么区别呢?

【问题讨论】:

【参考方案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 等成员(隐式实现)非常有意义。

【讨论】:

以上是关于C#接口的隐式和显式实现之间的区别[重复]的主要内容,如果未能解决你的问题,请参考以下文章

Oracle sql中的隐式和显式数据类型转换有啥区别

activity的隐式和显式启动

区别 b/w 在 C# 中隐式实现成员和显式实现成员 [重复]

关于隐式转换和显式转换

隐式<>显式接口[重复]

隐式与显式接口实现[重复]