2009-04-03 39 views

答えて

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 
0

ここでは、違いはあなたがいくつかのインタフェースからクラスを継承することができるということですMSDN

0

から直接、行きます。これらのインタフェースは、同一のメソッドシグネチャを持つことができます。明示的な実装では、Interfaceの呼び出しに応じて実装を変更することができます。

4

ExplicitはIInterfaceNameを指定します。すべてのインタフェース実装の前面に表示されます。衝突する名前/シグネチャを含む2つのインタフェースを実装する必要がある場合に便利です。

詳細情報here

10

IDEには、オプションがあります。両方を行うことは珍しいことです。明示的な実装では、メンバーは(プライマリ)パブリックAPIにはありません。これは、インタフェースがオブジェクトの意図に直接結ばれていないと便利です。たとえば、ICustomTypeDescriptorのメンバーは、通常の発信者にとって役立つものではありません。特定の特定のコードに対してのみ使用できます。そのため、パブリックAPIに混乱を招くような目的はありません。

また、これは場合に便利です:

  • は、インタフェースのFoo方法と、独自のタイプのFoo方法の間に矛盾がある、と彼らは異なることを意味
  • 他のインタフェース
  • を間署名の競合があります

最後のポイントの典型的な例はIEnumerable<T>であり、これはインターフェイス階層の2つのレベルでGetEnumerator()メソッドを持ちます。これはimpl暗黙の実装を使用して型付き(IEnumerator<T>)バージョンを、明示的実装を使用して型なし(IEnumerator)バージョンを作成します。

+1

明示的な実装は、アセンブリからパブリックにエクスポートしたくない内部インターフェイスをクラスが実装する必要がある場合にも便利です。 – Dave

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. 
0

明示的なインターフェイスの実装、: はここに明示的な実装の一例ですクラスの機能。つまり、行動的に無関係です。

たとえば、クラスがPersonでインターフェースがISerializableの場合、Person属性を扱う人がIntellisenseを介して 'GetObjectData'という名前の奇妙なものを見るのはあまり意味がありません。したがって、明示的にインターフェイスを実装したいことがあります。

一方、PersonクラスがIAddressを実装した場合、PersonインスタンスのAddressLine1、ZipCodeなどのメンバーを直接(暗黙の実装)見ることは理にかなっています。ここで

6

は平易な英語の違いです:

は、関数Run()、ともRun()呼ばれる機能を持っている別のインターフェイスAnimalを持つインタフェースMachineを、持っていると仮定します。もちろん、機械が走っている時、私たちはそれについて話していますが、動物が走ったら、動き回っていると話しています。オブジェクトを持っているとどうなりますか?Aiboと呼びましょう。MachineAnimalです。 (ちなみに、アイボは機械的な犬です。)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()を呼び出すことはできませんということです:明示的インターフェイスを実装することで、その区別を行うことができます。そうでなければ、コンパイラはどちらを呼び出すべきかを知っているでしょうか?代わりに、AiboRun()関数を直接呼びたい場合は、に明示的なインターフェイスなしで実装する必要があります。

関連する問題