C#接口的隐式和显式实现之间的区别

时间:2009-04-03 05:34:50

标签: c# interface

明确实现接口实现接口之间的区别是什么。

当您从界面派生类时,intellisense建议您同时执行这两个操作。

但是,有什么区别?

8 个答案:

答案 0 :(得分:13)

另一方面:

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

如果显式实现,客户端必须先将类转换为接口,然后才能访问成员。 以下是显式实现的示例:

    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

答案 1 :(得分:10)

IDE为您提供了选项 - 两种方法都不常见。通过显式实现,成员不在(主)公共API上;如果接口没有直接绑定到对象的意图,这是很方便的。例如,ICustomTypeDescriptor成员对常规调用者没有任何帮助 - 只对某些非常具体的代码有用,因此没有任何目的在公共API上使用它们导致混乱。

如果符合以下条件,这也很有用:

  • 界面的Foo方法与您自己类型的Foo方法之间存在冲突,它们意味着不同的事情
  • 其他接口之间存在签名冲突

最后一个点的典型示例是IEnumerable<T>,它在接口层次结构中的两个级别都有GetEnumerator()方法 - 通常使用类型化的(IEnumerator<T>)版本来实现隐式实现,以及使用显式实现的无类型(IEnumerator)版本。

答案 2 :(得分:6)

这是普通英语的区别:

假设您有一个接口Machine,其函数为Run(),另一个接口Animal也有一个名为Run()的函数。当然,当一台机器运行时,我们正在谈论它的启动,但是当一只动物跑来跑去时,我们正在谈论它的移动。那么当你有一个对象时会发生什么,让我们称之为AiboMachine的{​​{1}}? (顺便说一句,Aibo是一只机械狗。)当Animal跑步时,他是否开始行动,或者是否会四处走动?明确地实现一个接口可以让你做出这样的区分:

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()上的Run()函数,我必须在没有显式界面的情况下实现该函数。

答案 3 :(得分:4)

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

更多信息here

答案 4 :(得分:1)

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

    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.

答案 5 :(得分:0)

您可以直接从MSDN

开始

答案 6 :(得分:0)

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

答案 7 :(得分:0)

当接口与类功能正交时,显式接口实现(隐​​藏实现除非您显式转换)最有用。也就是说,行为无关。

例如,如果你的类是Person并且接口是ISerializable,那么处理Person属性的人通过Intellisense看到一些叫做'GetObjectData'的奇怪东西就没什么意义了。因此,您可能希望显式实现该接口。

另一方面,如果你的person类碰巧实现了IAddress,那么直接在Person实例上看到像AddressLine1,ZipCode等成员(隐式实现)是完全合理的。