C#接口的隐式实现和显式实现有什么区别?

9

“显式实现接口”和“实现接口”的区别是什么?

当您从接口派生一个类时,智能感知会建议您两者都进行。

但是,它们之间有什么不同呢?

8个回答

14

这方面的另一个方面是:

如果你实现了隐式接口,这意味着接口成员对于你类的用户是可访问的,而无需进行强制类型转换。

如果它被显式实现,客户端在访问成员之前必须将你的类转换为接口。以下是显式实现的示例:

    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

10

IDE提供了两种选择,不会同时使用。采用显式实现时,成员不在(主要的)公共API上;如果接口与对象本身的意图没有直接联系,则这非常方便。例如,ICustomTypeDescriptor成员对于常规调用者来说并不是特别有用,只有一些非常具体的代码才需要它们,因此没有把它们放在公共API上会更加清晰。

如果满足以下条件,也会很有用:

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

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


1
显式实现在你的类需要实现一个内部接口,但又不想从程序集中公开导出时非常有用。 - Dave

6
以下是通俗易懂的翻译:
假设您有一个接口 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

Explicit会将IInterfaceName.放在所有接口实现的前面。如果需要实现两个包含名称/签名冲突的接口,则此功能非常有用。

更多信息请点击这里


1

明确实现puts函数名的完全限定名称,请考虑以下代码

    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.

0

这里是直接来自MSDN的内容。


0

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


0

显式接口实现是指除非你明确转换,否则实现将被隐藏,当接口与类功能正交时,这种实现最为有用。也就是说,行为上不相关。

例如,如果你的类是Person,而接口是ISerializable,那么通过Intellisense看到一个奇怪的名为“GetObjectData”的东西对于处理Person属性的人来说并没有太多意义。因此,你可能希望明确地实现该接口。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接