Was ist der Unterschied zwischen der expliziten oder impliziten Implementierung einer Schnittstelle?

64

In Visual Studio kann ich mit der rechten Maustaste auf eine Schnittstelle klicken und entweder Schnittstelle implementieren oder Schnittstelle explizit implementieren.

Visual Studio-Screenshot

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(); }
    }
}

Der einzige Unterschied besteht darin, dass der Schnittstellenname zu den Schnittstelleneigenschaften und -methoden hinzugefügt wird, wenn Sie die Option zum expliziten Implementieren der Schnittstelle auswählen.

Ich finde, es macht den Code ein bisschen lesbarer, da ich sehen kann, woher diese Methode / Eigenschaft kommt. Aber macht dies einen Unterschied in der Verwendung oder Kompilierung der Klasse? Und ist es wirklich wichtig, ob ich meine Schnittstellen implizit oder explizit implementiere?

Rachel
quelle

Antworten:

51

Lesen Sie die Antwort von Andrew Barrett für "Implizite vs. explizite Schnittstellenimplementierung" auf SO .

Grundsätzlich gilt:

  • Implizit: Sie greifen auf die Schnittstellenmethoden und -eigenschaften zu, als wären sie Teil der Klasse.
  • Explizit: Sie können nur dann auf Methoden und Eigenschaften zugreifen, wenn Sie die Klasse als implementierte Schnittstelle behandeln.

Codebeispiele:

Implizit:

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

Ausdrücklich:

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

Wenn Sie ein Interface explizit implementieren müssen, ist dies der Fall, wenn Ihre Klasse bereits eine Methode mit derselben Signatur wie eine der Methoden Ihres Interfaces hat oder wenn Ihre Klasse mehrere Interfaces implementiert, die Methoden mit denselben Signaturen gemeinsam nutzen aber inkompatible Verträge.

Jalayn
quelle
1
Ich fand die explizite Implementierung auch nützlich, um eine Art "verstecktes" Interface mit unsicheren Operationen zu haben. Es macht auch Aufrufe zu diesen Methoden mehr auffällig, was eine gute Sache für unsichere Dinge ist.
Tamás Szelei
Erwähnenswert ist auch, dass die Verwendung expliziter Schnittstellen einen Leistungsaufwand verursacht, da das Objekt immer dann ein- und ausgeblendet werden muss, wenn Sie auf die Eigenschaft / Methode verweisen. Aus diesem Grund ist es besser, wenn möglich implizite Schnittstellen zu verwenden
Rachel
3
@ Rachel: Soweit mir bekannt ist, gelten die Performancekosten nur für Werttypen.
Groky
8

Es gibt auch einen Unterschied darin, wie Sie die Methode aufrufen.

Wenn Sie eine explizite Schnittstellenimplementierung verwenden, müssen Sie den Schnittstellentyp verwenden, um diese bestimmte Implementierung aufzurufen.

Wenn Sie also Code aufrufen, müssen Sie eine Variable vom Typ verwenden, ITestum darauf zuzugreifen ITest.Id.

Der Artikel Explizite Schnittstellenimplementierung (C # -Programmierhandbuch) auf MSDN enthält ein gutes Beispiel.

Oded
quelle
4

Sie können zwei Schnittstellen implementieren, die dieselbe Methode definieren. Wenn Sie die Schnittstelle jedoch explizit implementieren, kann auf die Methoden nur zugegriffen werden, wenn die Variable in diese explizite Schnittstelle eingegeben wird.

Siehe: Tutorial zur expliziten Schnittstellenimplementierung

unholysampler
quelle
4

BEARBEITEN: Es sollte keinen Unterschied machen Sie sollten es nicht tun, es sei denn, Ihre Klasse implementiert zwei Schnittstellen mit den gleichen Eigenschaften, da Sie auf die entsprechende Schnittstelle umwandeln müssen, bevor Sie auf das Mitglied zugreifen können:

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);
    }
}

Die Beispielverwendung gilt, wenn Sie explizit ein Schnittstellenmitglied implementieren, auch wenn Sie nur eine einzige Schnittstelle verwenden (was ich immer vergesse: S). Daher würde ich versuchen, die explizite Implementierung nach Möglichkeit zu vermeiden, da Klassenmitglieder ausgeblendet werden, wenn sie Es wird nicht auf die richtige Schnittstelle geworfen (was ziemlich verwirrend ist).

Ed James
quelle
3

Basierend auf der Antwort von Jalayan,

  • Implizit: Sie greifen auf die Schnittstellenmethoden und -eigenschaften zu, als wären sie Teil der Klasse.
  • Explizit: Sie können nur dann auf Methoden und Eigenschaften zugreifen, wenn Sie die Klasse als implementierte Schnittstelle behandeln.

Bildbeschreibung hier eingeben

Alexander Zaldostanov
quelle