Dies ist eine Frage zu den Erweiterungsmethoden von C # und ihrer Entwurfsphilosophie. Ich denke, die beste Möglichkeit, diese Frage zu beantworten, besteht darin, die Dokumentation von MSDN zum Zweck der Erweiterungsmethoden zu zitieren :
Mit Erweiterungsmethoden können Sie vorhandenen Typen Methoden "hinzufügen", ohne einen neuen abgeleiteten Typ zu erstellen, den ursprünglichen Typ neu zu kompilieren oder auf andere Weise zu ändern. Erweiterungsmethoden sind eine spezielle statische Methode, werden jedoch so aufgerufen, als wären sie Instanzmethoden des erweiterten Typs. Für Client-Code, der in C #, F # und Visual Basic geschrieben wurde, besteht kein offensichtlicher Unterschied zwischen dem Aufrufen einer Erweiterungsmethode und den Methoden, die tatsächlich in einem Typ definiert sind.
…
Im Allgemeinen empfehlen wir, Erweiterungsmethoden sparsam und nur dann zu implementieren, wenn dies erforderlich ist. Client-Code, der einen vorhandenen Typ erweitern muss, sollte dies nach Möglichkeit tun, indem ein neuer Typ erstellt wird, der von dem vorhandenen Typ abgeleitet ist. Weitere Informationen finden Sie unter Vererbung.
Wenn Sie eine Erweiterungsmethode zum Erweitern eines Typs verwenden, dessen Quellcode Sie nicht ändern können, besteht das Risiko, dass eine Änderung der Implementierung des Typs zu einem Absturz Ihrer Erweiterungsmethode führt.
Wenn Sie Erweiterungsmethoden für einen bestimmten Typ implementieren, beachten Sie die folgenden Punkte:
- Eine Erweiterungsmethode wird niemals aufgerufen, wenn sie dieselbe Signatur wie eine im Typ definierte Methode hat.
- Erweiterungsmethoden werden auf Namespace-Ebene in den Geltungsbereich aufgenommen. Wenn Sie beispielsweise mehrere statische Klassen haben, die Erweiterungsmethoden in einem einzigen Namespace enthalten
Extensions
, werden diese durch die using Extensions;
Direktive alle in den Geltungsbereich aufgenommen.
Zusammenfassend lässt sich sagen, dass Erweiterungsmethoden so konzipiert sind, dass sie einem bestimmten Typ Instanzmethoden hinzufügen, auch wenn die Entwickler dies nicht direkt können. Und da Instanzmethoden Erweiterungsmethoden immer überschreiben, wenn sie vorhanden sind (wenn sie mithilfe der Instanzmethodensyntax aufgerufen werden), sollte dies nur erfolgen, wenn Sie keine Methode direkt hinzufügen oder die Klasse erweitern können. *
Mit anderen Worten, eine Erweiterungsmethode sollte genau wie eine Instanzmethode funktionieren, da sie möglicherweise von einem Client zu einer Instanzmethode gemacht wird. Und weil eine Instanzmethode werfen sollte, wenn das Objekt, für das sie aufgerufen wird null
, ist , sollte dies auch die Erweiterungsmethode tun.
* Als Randbemerkung ist dies genau die Situation, mit der die Designer von LINQ konfrontiert waren: Als C # 3.0 veröffentlicht wurde, gab es bereits Millionen von Clients, die System.Collections.IEnumerable
und verwendeten System.Collections.Generic.IEnumerable<T>
, sowohl in ihren Sammlungen als auch in foreach
Schleifen. Diese Klassen zurück IEnumerator
Objekte , die nur hatten die beiden Methoden Current
und MoveNext
, so das Hinzufügen alle zusätzliche erforderliche Instanzmethoden, wie zum Beispiel Count
, Any
usw., würde diese Millionen von Kunden brechen. Also, um diese Funktionalität bereitzustellen (vor allem , da es in Bezug auf die umgesetzt werden können Current
und MoveNext
mit relativer Leichtigkeit), veröffentlichten sie es als Erweiterungsmethoden, die auf jede derzeit angewendet werden , können bestehendeIEnumerable
Instanz und kann auch von Klassen auf effizientere Weise implementiert werden. Hätten die Entwickler von C # beschlossen, LINQ am ersten Tag freizugeben, wäre es als Instanzmethode von bereitgestellt worden IEnumerable
, und sie hätten wahrscheinlich eine Art System entworfen, das Standardschnittstellenimplementierungen dieser Methoden bereitstellt.