Meistens verwende ich eine explizite Schnittstellenimplementierung. Hier sind die Hauptgründe.
Refactoring ist sicherer
Wenn Sie eine Schnittstelle ändern, ist es besser, wenn der Compiler dies überprüfen kann. Dies ist bei impliziten Implementierungen schwieriger.
Zwei häufige Fälle kommen mir in den Sinn:
-
Hinzufügen einer Funktion zu einer Schnittstelle, wenn eine bestehende Klasse, die diese Schnittstelle implementiert, bereits eine Methode mit der gleichen Signatur wie die neue hat . Dies kann zu unerwartetem Verhalten führen und hat mich schon einige Male hart getroffen. Bei der Fehlersuche ist es schwer zu "sehen", weil diese Funktion wahrscheinlich nicht zusammen mit den anderen Schnittstellenmethoden in der Datei zu finden ist (das unten erwähnte Problem der Selbstdokumentation).
-
Entfernen einer Funktion aus einer Schnittstelle . Implizit implementierte Methoden werden plötzlich zu totem Code, aber explizit implementierte Methoden werden durch einen Kompilierfehler abgefangen. Selbst wenn der tote Code gut ist, möchte ich gezwungen sein, ihn zu überprüfen und zu fördern.
Leider gibt es in C# kein Schlüsselwort, das uns zwingt, eine Methode als implizite Implementierung zu kennzeichnen, so dass der Compiler die zusätzlichen Prüfungen durchführen könnte. Virtuelle Methoden haben keines der oben genannten Probleme aufgrund der erforderlichen Verwendung von 'override' und 'new'.
Hinweis: Für feste oder sich selten ändernde Schnittstellen (typischerweise von Anbieter-APIs) ist dies kein Problem. Bei meinen eigenen Schnittstellen kann ich jedoch nicht vorhersagen, wann/wie sie sich ändern werden.
Es ist selbstdokumentierend
Wenn ich in einer Klasse 'public bool Execute()' sehe, wird es zusätzliche Arbeit kosten, herauszufinden, dass es Teil einer Schnittstelle ist. Jemand wird sie wahrscheinlich mit einem entsprechenden Kommentar versehen oder sie in eine Gruppe anderer Schnittstellenimplementierungen einordnen müssen, die alle unter einer Region oder einem Gruppenkommentar stehen, der besagt "implementation of ITask". Das funktioniert natürlich nur, wenn der Gruppenkopf nicht außerhalb des Bildschirms liegt
in Erwägung nachstehender Gründe 'bool ITask.Execute()' ist klar und unmissverständlich.
Klare Trennung der Schnittstellenimplementierung
Ich betrachte Schnittstellen als "öffentlicher" als öffentliche Methoden, weil sie so gestaltet sind, dass sie nur einen kleinen Teil der Oberfläche des konkreten Typs offenlegen. Sie reduzieren den Typ auf eine Fähigkeit, ein Verhalten, eine Reihe von Merkmalen usw. Und bei der Implementierung halte ich es für sinnvoll, diese Trennung beizubehalten.
Wenn ich mir den Code einer Klasse ansehe und auf explizite Schnittstellenimplementierungen stoße, schaltet mein Gehirn in den Modus "Codevertrag". Oft leiten diese Implementierungen einfach an andere Methoden weiter, aber manchmal führen sie zusätzliche Zustands-/Parameterprüfungen durch, konvertieren eingehende Parameter, um den internen Anforderungen besser zu entsprechen, oder übersetzen sogar zu Versionszwecken (d. h. mehrere Generationen von Schnittstellen, die alle auf gemeinsame Implementierungen zurückgehen).
(Mir ist klar, dass Publics auch Codekontrakte sind, aber Schnittstellen sind viel stärker, insbesondere in einer schnittstellengesteuerten Codebasis, in der die direkte Verwendung konkreter Typen normalerweise ein Zeichen für reinen internen Code ist).
Verwandt: Grund 2 oben von Jon .
Und so weiter
Hinzu kommen die Vorteile, die bereits in anderen Antworten hier genannt wurden:
Probleme
Es geht nicht nur um Spaß und Glück. Es gibt einige Fälle, in denen ich mich an Andeutungen halte:
- Werttypen, denn das erfordert Boxing und geringere Leistung. Dies ist keine strikte Regel und hängt von der Schnittstelle ab und davon, wie sie verwendet werden soll. IComparable? Implizit. IFormattable? Wahrscheinlich explizit.
- Triviale Systemschnittstellen, die Methoden haben, die häufig direkt aufgerufen werden (wie IDisposable.Dispose).
Außerdem kann es mühsam sein, das Casting durchzuführen, wenn man tatsächlich den konkreten Typ hat und eine explizite Schnittstellenmethode aufrufen möchte. Ich gehe damit auf zwei Arten um:
- Fügen Sie Publics hinzu und lassen Sie die Methoden der Schnittstelle für die Implementierung an diese weiterleiten. Dies geschieht in der Regel bei einfacheren Schnittstellen, wenn man intern arbeitet.
- (Meine bevorzugte Methode) Fügen Sie eine
public IMyInterface I { get { return this; } }
(das inlined werden sollte) und rufen foo.I.InterfaceMethod()
. Bei mehreren Schnittstellen, die diese Fähigkeit benötigen, erweitern Sie den Namen über I hinaus (meiner Erfahrung nach ist es selten, dass ich diese Notwendigkeit habe).
0 Stimmen
Vollständigen Artikel über C#-Schnittstellen lesen : planetofcoders.com/c-schnittstellen
1 Stimmen
Ja, explizite Schnittstellen sollten vermieden werden, und ein professionellerer Ansatz wäre die Implementierung von ISP (Schnittstellentrennungsprinzip) - hier ein ausführlicher Artikel dazu codeproject.com/Artikel/1000374/
0 Stimmen
In den meisten Fällen werden Schnittstellen nicht benötigt, denken Sie darüber nach, wer Ihren Code verwendet, niemand, also verschwenden Sie keine Zeit mit dem Versuch, die besten Schnittstellen zu implementieren, Schnittstellen erhöhen nur die Komplexität des Projekts und führen zu mehr Funktionsfehlern, als es sein sollte