インターフェイスを明示的または暗黙的に実装することの違いは何ですか?


64

Visual Studioでは、インターフェイスを右クリックして、[インターフェイスの実装]または[インターフェイスの明示的な実装]を選択できます。

Visual Studioスクリーンショット

public class Test : ITest
{
    public string Id // Generated by Implement Interface
    {
        get { throw new NotImplementedException(); }
    }

    string ITest.Id // Generated by Implement Interface Explicitly
    {
        get { throw new NotImplementedException(); }
    }
}

この2つの間に見られる唯一の違いは、インターフェイスを明示的に実装することを選択した場合、作成時にインターフェイスのプロパティとメソッドにインターフェイス名が追加されることです。

そのメソッド/プロパティがどこから来たのかを見ることができるので、コードが少し読みやすくなりますが、これはクラスの使用方法やコンパイル方法に違いをもたらしますか?暗黙的または明示的にインターフェイスを実装する場合、それは本当に重要ですか?

回答:


51

SOでの「暗黙的vs明示的なインターフェースの実装」については、Andrew Barrettのトップの回答をご覧ください。

基本的に:

  • 暗黙的:インターフェースのメソッドとプロパティは、クラスの一部であるかのようにアクセスします。
  • 明示的:クラスを実装されたインターフェースとして扱う場合にのみ、メソッドとプロパティにアクセスできます。

コード例:

暗黙:

Test t = new Test();
t.Id; // OK
((ITest)t).Id; // OK

明示的:

Test t = new Test();
t.Id; // Not OK
((ITest)t).Id; // OK

インターフェースを明示的に実装する必要がある場合は、クラスにすでにインターフェースのメソッドの1つと同じシグネチャを持つメソッドがある場合、またはクラスが同じシグネチャを持つメソッドを共有する複数のインターフェースを実装している場合です。しかし、互換性のない契約。


1
また、安全でない操作を伴う一種の「隠された」インターフェースを持つために、明示的な実装が有用であることがわかりました。また、これらのメソッドへの呼び出しをより際立たせており、安全でないものには良いことです。
タマスゼレイ

プロパティ/メソッドを参照するたびにオブジェクトをボックス化/ボックス化解除する必要があるため、明示的なインターフェイスの使用にはパフォーマンスコストがかかることにも言及する価値があります。このため、可能であれば暗黙的なインターフェイスを使用することをお勧めします
レイチェル

3
@レイチェル:私の知る限り、パフォーマンスコストは値の型にのみ適用されることを知っています。
グロッキー

8

メソッドの呼び出し方法にも違いがあります。

使用する場合は、明示的なインターフェイスの実装を、あなたはその特定の実装を呼び出すためにインターフェイスタイプを使用する必要があります。

そのため、コードを呼び出すには、ITestにアクセスするために型の変数を使用する必要がありますITest.Id

MSDN の記事「明示的なインターフェイスの実装(C#プログラミングガイド)」に良い例があります。



4

編集: 違い はないはずですメンバーにアクセスする前に関連するインターフェースにキャストする必要があるため、クラスが同じプロパティを持つ2つのインターフェースを実装ない限り、それを行うべきではありません

public interface ITest
{
    string Id { get; }
}

public interface IAlsoTest
{
    string Id { get; }
}

public interface ITestToo
{
    int Id { get; }
}

public class Test : ITest, IAlsoTest
{
    // Valid implicit implementation of BOTH interfaces
    public string Id
    {
        get { throw new NotImplementedException(); }
    }
}

public class TestSeparately : ITest, ITestToo
{
    // This way we can do different things depending
    // on which interface the callee called from.
    string ITest.Id
    {
        get { throw new NotImplementedException(); }
    }

    int ITestToo.Id
    {
        get { throw new NotImplementedException(); }
    }
}

public class TestOuch
{
    public void DoStuff()
    {
        var ts = new TestSeparately();

        // Works
        Console.WriteLine(((ITest)ts).Id);

        // Works
        Console.WriteLine(((ITestToo)ts).Id);

        // Not valid! Which one did we want to call?
        Console.WriteLine(ts.Id);
    }
}

例の使用法は、単一のインターフェイス(私はいつも忘れる:S)のみを使用している場合でも、インターフェイスメンバーを明示的に実装する場合に保持されるため、可能な場合はクラスメンバーを非表示にするため、可能な場合は明示的な実装を避けようとします正しいインターフェイスにキャストしないでください(かなり混乱します)。


3

ジャラヤンの答えに基づいて、

  • 暗黙的:インターフェースのメソッドとプロパティは、クラスの一部であるかのようにアクセスします。
  • 明示的:クラスを実装されたインターフェースとして扱う場合にのみ、メソッドとプロパティにアクセスできます。

ここに画像の説明を入力してください

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.