您的位置:首页 > 其它

显示实现和隐式实现接口的区别(Implicit and Explicit Interface Implementations)

2012-11-25 22:59 519 查看
Implicit and Explicit Interface Implementations
Rate This

mhop
13 Dec 2006 2:59 AM
19
As I was putting together a post on
IEnumerable andIEnumerator Iwas reminded of the subtleties of implicit
and explicit interfaceimplementations. C# does not support multiple inheritance, but a class has theoption of implementing one or more interfaces. One challenge with interfaces isthat they may include methods that have the same signatures as existing classmembers
or members of other interfaces. Explicit interface implementations canbe used to disambiguate class and interface methods that would otherwiseconflict. Explicit interfaces can also be used to hide the details of aninterface that the class developer considers
private.
Disambiguating Methods
Let's look at an example of method disambiguation. In Listing 1 we havestarted to write a class calledC that implements interfaces
I1and I2, each of which defines a methodA().
Listing 1. Class C implements interfaces I1 and I2.
interface I1
{
    void A();
}
 
interface I2
{
    void A();
}
 
class C : I1, I2
{
    public void A()
    {
       Console.WriteLine("C.A()");
    }
}
In this case, A() is a public class member that
implicitlyimplements a member of both interfaces. A() can be invokedthrough either interface or through the class itself as follows:
Listing 2. A() can be invoked from I1, I2, or C.
C c = new C();
I1 i1 = (I1)c;
I2 i2 = (I2)c;
 
i1.A();
i2.A();
c.A();
The output from this code is
C.A()
C.A()
C.A()
This works fine if you want A() to do the same thing in bothinterfaces. In most cases, however, methods in different interfaces havedistinct purposes requiring wholly different implementations. This is whereexplicit interface
implementations come in handy. To explicitly implement aninterface member, just use its fully qualified name in the declaration. A fullyqualified interface name takes the form
InterfaceName.MemberName
In Listing 3 we add an explicit implementation of I1'sA()method.
Listing 3. Class C explicitly implements I1.A().
class C : I1, I2
{
    public void A()
    {
       Console.WriteLine("C.A()");
    }
 
    void I1.A()
    {
       Console.WriteLine("I1.A()");
    }
}
Now when we run the statements from Listing 2 we get
I1.A()
C.A()
C.A()
When an interface method is explicitly implemented, it is no longervisible as a public member of the class. The only way to access it is throughthe interface. As an example, suppose we deleted the implicitimplementation ofA()
as shown in Listing 4:
Listing 4. Class C does not implicitly implement A()
class C : I1, I2
{
    void I1.A()
    {
       Console.WriteLine("I2.A()");
    }
}
In this case we would get a compile error saying that C fails toimplementI2.A(). We could fix this error by changing the first line to
class C : I1
but we'd get another compile error when trying to invoke
A()
as amember of C:
C c = new C();
c.A();
This time the compiler would report that class C does not contain adefinition for methodA(). We get the error because the explicitimplementation of
I1.A() hides A() from the class. The only wayto call
I1.A() now is through C's I1 interface:
C c = new C();
I1 i1 = (I1)c;
i1.A();
Explicit interface implementations are sometimes necessary when classesimplement multiple interfaces with conflicting member definitions. A commonexample involves collection enumerators that implementSystem.Collections.IEnumeratorand

System.Collections.Generic.IEnumerator. In this case both interfaces specify a get-accessor for theCurrentproperty. To
create a class that compiles, at least one of the twoget-accessors must be explicitly implemented.
Hiding Interface Details.
In some cases explicit interface implementation can be useful even whendisambiguation is unnecessary. One example is to use an explicit implementationto hide the details of an interface that the class developer considers private.While the level
of privacy is not as great as that afforded by the
privatekeyword, it can be useful in some circumstances. Listing 5 shows a commonpattern involvingIDisposable.In
this case, the Dispose() method is hidden by explicit implementationbecause the method is really an implementation detail that is notgermane to the users of classMyFile. At the very least, the explicitimplementation keeps
the interface members out of the class'Intellisenselist.

Listing 5. Using explicit implementation to hide the details ofIDisposable.
interface IDisposable
{
    void Dispose();
}
 
class MyFile : IDisposable
{
    void IDisposable.Dispose()
    {
        Close();
    }
 
    public voidClose()
    {
        // Dowhat's necessary to close the file
       System.GC.SuppressFinalize(this);
    }
}
You can read more about implicit and explicit interface implementations inthisMSDNTutorial
or in
Version 1.2 ofthe C# Language Specification.
 
Hope this helps.
 
-Mike Hopcroft
 

 转自 http://bbs.csdn.net/topics/320002324
在MSDN上原文:http://msdn.microsoft.com/en-us/library/ms173157.aspx

如果类实现两个接口,并且这两个接口包含具有相同签名的成员,那么在类中实现该成员将导致两个接口都使用该成员作为它们的实现。例如: 

C#  复制代码 

interface IControl

{

    void Paint();

}

interface ISurface

{

    void Paint();

}

class SampleClass : IControl, ISurface

{

    // Both ISurface.Paint and IControl.Paint call this method.

    public void Paint()

    {

    }

}

 

然而,如果两个接口成员执行不同的函数,那么这可能会导致其中一个接口的实现不正确或两个接口的实现都不正确。可以显式地实现接口成员 -- 即创建一个仅通过该接口调用并且特定于该接口的类成员。这是使用接口名称和一个句点命名该类成员来实现的。例如: 

C#  复制代码 

public class SampleClass : IControl, ISurface

{

    void IControl.Paint()

    {

        System.Console.WriteLine("IControl.Paint");

    }

    void ISurface.Paint()

    {

        System.Console.WriteLine("ISurface.Paint");

    }

}

 

类成员 IControl.Paint 只能通过 IControl 接口使用,ISurface.Paint 只能通过 ISurface 使用。两个方法实现都是分离的,都不可以直接在类中使用。例如: 

C#  复制代码 

SampleClass obj = new SampleClass();

//obj.Paint();  // Compiler error.

IControl c = (IControl)obj;

c.Paint();  // Calls IControl.Paint on SampleClass.

ISurface s = (ISurface)obj;

s.Paint(); // Calls ISurface.Paint on SampleClass.

 

显式实现还用于解决两个接口分别声明具有相同名称的不同成员(如属性和方法)的情况: 

C#  复制代码 

interface ILeft

{

    int P { get;}

}

interface IRight

{

    int P();

}

 

为了同时实现两个接口,类必须对属性 P 和/或方法 P 使用显式实现以避免编译器错误。例如: 

C#  复制代码 

class Middle : ILeft, IRight

{

    public int P() { return 0; }

    int ILeft.P { get { return 0; } }

}

自己动手试一试的冲动有没有??(~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: