Ein "Ungläubiger" von C # fragte mich, was der Zweck von Erweiterungsmethoden sei. Ich erklärte, dass Sie dann bereits definierten Objekten neue Methoden hinzufügen können, insbesondere wenn Sie die Quelle des ursprünglichen Objekts nicht besitzen / steuern.
Er sprach: "Warum nicht einfach eine Methode zu deiner eigenen Klasse hinzufügen?" Wir sind herumgegangen (auf eine gute Art und Weise). Meine allgemeine Antwort ist, dass es ein weiteres Werkzeug im Werkzeuggürtel ist, und seine Antwort ist, dass es eine nutzlose Verschwendung eines Werkzeugs ist ... aber ich dachte, ich würde eine "aufgeklärtere" Antwort bekommen.
In welchen Szenarien haben Sie Erweiterungsmethoden verwendet, für die Sie keine Methode hätten verwenden können (oder sollten), die Ihrer eigenen Klasse hinzugefügt wurde?
quelle
Extensions.To(1, 10)
ist bedeutungslos und1.To(10)
beschreibend. Natürlich verstehe ich die technische Seite, von der Sie sprechen, nur um es zu sagen. Tatsächlich gibt es Szenarien, in denen ein Erweiterungsansatz anstelle statischer Methoden " nicht hätte verwendet werden können", beispielsweise Reflexion, ein anderer Falldynamic
.Antworten:
Ich denke, Erweiterungsmethoden helfen beim Schreiben von Code sehr. Wenn Sie Basistypen Erweiterungsmethoden hinzufügen, erhalten Sie diese schnell im Intellisense.
Ich habe einen Formatanbieter zum Formatieren einer Dateigröße . Um es zu benutzen, muss ich schreiben:
Erstellen einer Erweiterungsmethode, die ich schreiben kann:
Sauberer und einfacher.
quelle
LongToFileSize(fileSize)
, was genauso prägnant und wohl genauso klar ist.Der einzige Vorteil von Erweiterungsmethoden ist die Lesbarkeit des Codes. Das ist es.
Mit den Erweiterungsmethoden können Sie Folgendes tun:
an Stelle von:
Jetzt gibt es in C # viele Dinge, die so sind. Mit anderen Worten, es gibt viele Funktionen in C #, die trivial erscheinen und an und für sich keinen großen Nutzen haben. Sobald Sie jedoch anfangen, diese Funktionen miteinander zu kombinieren, sehen Sie etwas, das nur ein bisschen größer ist als die Summe seiner Teile. LINQ profitiert stark von Erweiterungsmethoden, da LINQ-Abfragen ohne sie fast nicht lesbar wären. LINQ wäre möglich ohne Erweiterungsmethoden, aber nicht praktikabel.
Erweiterungsmethoden ähneln stark den Teilklassen von C #. An sich sind sie nicht sehr hilfreich und scheinen trivial. Wenn Sie jedoch mit einer Klasse arbeiten, die generierten Code benötigt, sind Teilklassen viel sinnvoller.
quelle
Werkzeuge nicht vergessen! Wenn Sie eine Erweiterungsmethode M für den Typ Foo hinzufügen, erhalten Sie 'M' in der Intellisense-Liste von Foo (vorausgesetzt, die Erweiterungsklasse ist im Gültigkeitsbereich). Dadurch ist 'M' viel einfacher zu finden als MyClass.M (Foo, ...).
Letztendlich ist es nur syntaktischer Zucker für anderswo statische Methoden, aber wie beim Kauf eines Hauses: 'Ort, Ort, Ort!' Wenn es am Typ hängt, werden die Leute es finden!
quelle
String
), die eine ziemlich lange Liste von Instanzmethoden enthalten, sodass dieses Problem nicht spezifisch für Erweiterungsmethoden ist.Zwei weitere Vorteile von Erweiterungsmethoden, auf die ich gestoßen bin:
Select(...)
,Where(...)
usw. Hung von derIEnumerable<T>
Schnittstelle.quelle
Einige der besten Anwendungen, die ich für Erweiterungsmethoden hatte, sind die folgenden Möglichkeiten:
sealed
.Nehmen Sie zum Beispiel ,
IEnumerable<T>
. Obwohl es reich an Erweiterungsmethoden ist, fand ich es ärgerlich, dass keine generische ForEach-Methode implementiert wurde. Also habe ich meine eigenen gemacht:Voila, alle meine
IEnumerable<T>
Objekte, unabhängig vom Implementierungstyp, und ob ich sie geschrieben habe oder jemand anderes, hatten jetzt eineForEach
Methode, indem sie eine entsprechende "using" -Anweisung in meinen Code einfügten.quelle
Einer der Hauptgründe für die Verwendung von Erweiterungsmethoden ist LINQ. Ohne Erweiterungsmethoden wäre vieles, was Sie in LINQ tun können, sehr schwierig. Die Erweiterungsmethoden Where (), Contains (), Select bedeuten, dass vorhandenen Typen viel mehr Funktionen hinzugefügt werden, ohne dass ihre Struktur geändert wird.
quelle
Es gibt viele Antworten auf die Vorteile von Erweiterungsmethoden. Wie wäre es mit einem, der die Nachteile angeht ?
Der größte Nachteil ist, dass es keinen Compilerfehler oder eine Warnung gibt, wenn Sie eine reguläre Methode und eine Erweiterungsmethode mit derselben Signatur im selben Kontext haben.
Angenommen, Sie erstellen eine Erweiterungsmethode, die auf eine bestimmte Klasse angewendet wird. Später erstellt jemand eine Methode mit einer identischen Signatur für diese Klasse.
Ihr Code wird kompiliert und Sie erhalten möglicherweise nicht einmal einen Laufzeitfehler. Sie führen jedoch nicht mehr denselben Code wie zuvor aus.
quelle
Fließende Schnittstellen und Kontextsensitivität, wie von Greg Young auf CodeBetter demonstriert
quelle
Mein persönliches Argument für Erweiterungsmethoden ist, dass sie sehr gut in ein OOP-Design passen: Betrachten Sie die einfache Methode
im Vergleich zu
quelle
Oben finden Sie unzählige gute Antworten darauf, welche Erweiterungsmethoden Sie verwenden können.
Meine kurze Antwort lautet: Sie machen Fabriken fast überflüssig.
Ich möchte nur darauf hinweisen, dass sie kein neues Konzept sind und eine der größten Bestätigungen dafür ist, dass sie ein Killer-Feature in Objective-C ( Kategorien ) sind. Sie bieten der Framework-basierten Entwicklung so viel Flexibilität, dass NeXT Finanzmodellierer der NSA und der Wall Street als Hauptnutzer hatte.
REALbasic implementiert sie auch als erweiterte Methoden und sie waren dort von ähnlichem Nutzen, um die Entwicklung zu vereinfachen.
quelle
Ich möchte die anderen Antworten hier unterstützen, die eine verbesserte Lesbarkeit des Codes als wichtigen Grund für Erweiterungsmethoden erwähnen. Ich werde dies anhand von zwei Aspekten demonstrieren: Methodenverkettung im Vergleich zu verschachtelten Methodenaufrufen und Unordnung einer LINQ-Abfrage mit bedeutungslosen statischen Klassennamen.
Nehmen wir diese LINQ-Abfrage als Beispiel:
Beide
Where
undSelect
sind Erweiterungsmethoden, die in der statischen Klasse definiert sindEnumerable
. Wenn also keine Erweiterungsmethoden vorhanden wären und dies normale statische Methoden wären, müsste die letzte Codezeile im Wesentlichen so aussehen:Sehen Sie, wie viel fieser diese Abfrage gerade geworden ist.
Zweitens, wenn Sie jetzt Ihren eigenen Abfrageoperator einführen möchten, haben Sie natürlich keine Möglichkeit, ihn innerhalb der
Enumerable
statischen Klasse zu definieren, wie alle anderen Standardabfrageoperatoren, da erEnumerable
sich im Framework befindet und Sie keine Kontrolle über diese Klasse haben. Daher müssten Sie Ihre eigene statische Klasse definieren, die Erweiterungsmethoden enthält. Möglicherweise erhalten Sie dann Fragen wie diese:quelle
Es ist wahr, dass Sie Ihre (Erweiterungs-) Methode direkt zu Ihrer Klasse hinzufügen können. Aber nicht alle Klassen werden von Ihnen geschrieben. Klassen aus der Kernbibliothek oder Bibliotheken von Drittanbietern werden häufig geschlossen, und es wäre unmöglich, den syntatischen Zucker ohne Erweiterungsmethoden zu erhalten. Denken Sie jedoch daran, dass Erweiterungsmethoden wie (statische) eigenständige Methoden in z. c ++
quelle
Erweiterungsmethoden können auch dazu beitragen, Ihre Klassen und Klassenabhängigkeiten sauber zu halten. Beispielsweise benötigen Sie möglicherweise überall dort, wo Foo verwendet wird, eine Bar () -Methode für die Foo-Klasse. Möglicherweise möchten Sie jedoch eine .ToXml () -Methode in einer anderen Assembly und nur für diese Assembly. In diesem Fall können Sie die erforderlichen System.Xml- und / oder System.Xml.Linq-Abhängigkeiten in dieser Assembly und nicht in der ursprünglichen Assembly hinzufügen.
Vorteile: Abhängigkeiten in Ihrer definierenden Klassenassembly werden nur auf das Nötigste reduziert, und andere konsumierende Assemblys können die ToXml () -Methode nicht verwenden. Weitere Informationen finden Sie in dieser PDC-Präsentation .
quelle
Ich bin damit einverstanden, dass Erweiterungsmethoden die Lesbarkeit von Code verbessern, aber es ist wirklich nichts anderes als statische Hilfsmethoden.
IMO, das Erweiterungsmethoden zum Hinzufügen von Verhalten zu Ihren Klassen verwendet, kann sein:
Verwirrend: Programmierer glauben möglicherweise, dass Methoden Teil des erweiterten Typs sind, und verstehen daher nicht, warum die Methoden weg sind, wenn der Erweiterungs-Namespace nicht importiert wird.
Ein Antimuster: Sie beschließen, Typen in Ihrem Framework mithilfe von Erweiterungsmethoden Verhalten hinzuzufügen und sie dann an eine Person weiterzuleiten, die sie einem Komponententest unterzieht. Jetzt steckt er in einem Framework fest, das eine Reihe von Methoden enthält, die er nicht vortäuschen kann.
quelle
Erweiterungsmethoden sind eigentlich die .NET-Integration des Refactors "Introduce Foreign Method" aus Martin Fowlers Buch (bis hin zur Methodensignatur). Sie haben im Grunde die gleichen Vorteile und Fallstricke. In dem Abschnitt über diesen Refactor sagt er, dass sie eine Problemumgehung sind, wenn Sie die Klasse nicht ändern können, die die Methode wirklich besitzen sollte.
quelle
Ich sehe Erweiterungsmethoden hauptsächlich als ein Eingeständnis, dass sie freie Funktionen vielleicht nicht unzulässig hätten sein dürfen.
In der C ++ - Community wird es häufig als gute OOP-Praxis angesehen, kostenlose Nichtmitgliedsfunktionen gegenüber Mitgliedern zu bevorzugen, da diese Funktionen die Kapselung nicht unterbrechen, indem sie Zugriff auf nicht benötigte private Mitglieder erhalten. Erweiterungsmethoden scheinen ein Umweg zu sein, um dasselbe zu erreichen. Das heißt, eine sauberere Syntax für statische Funktionen, die keinen Zugriff auf private Mitglieder haben.
Erweiterungsmethoden sind nichts anderes als syntaktischer Zucker, aber ich sehe keinen Schaden darin, sie zu verwenden.
quelle
quelle
Ich verwende sie, um meine Objektmodellklassen wiederzuverwenden. Ich habe eine Reihe von Klassen, die Objekte darstellen, die ich in einer Datenbank habe. Diese Klassen werden auf der Clientseite nur zum Anzeigen der Objekte verwendet, sodass die grundlegende Verwendung der Zugriff auf Eigenschaften ist.
Aufgrund dieses Verwendungsmusters möchte ich keine Geschäftslogikmethoden in diesen Klassen haben, daher mache ich jede Geschäftslogik zu einer Erweiterungsmethode.
Auf diese Weise kann ich dieselben Klassen für die Geschäftslogikverarbeitung und für die Anzeige der Benutzeroberfläche verwenden, ohne die Clientseite mit unnötigem Code zu überladen.
Eine interessante Sache an dieser Lösung ist, dass meine Objektmodellklassen dynamisch mit Mono.Cecil generiert werden. Daher wäre es sehr schwierig, Geschäftslogikmethoden hinzuzufügen, selbst wenn ich dies wollte. Ich habe einen Compiler, der XML-Definitionsdateien liest und diese Stubs-Klassen generiert, die ein Objekt darstellen, das ich in der Datenbank habe. Der einzige Ansatz in diesem Fall besteht darin, sie zu erweitern.
quelle
Damit kann C # dynamische Sprachen, LINQ und ein Dutzend anderer Dinge besser unterstützen. Lesen Sie den Artikel von Scott Guthrie .
quelle
In meinem letzten Projekt habe ich die Erweiterungsmethode verwendet, um Validate () -Methoden an Geschäftsobjekte anzuhängen. Ich habe dies begründet, weil die Geschäftsobjekte serialisierbare Datenübertragungsobjekte sind und in verschiedenen Domänen verwendet werden, da sie allgemeine E-Commerce-Entitäten wie Produkte, Kunden, Händler usw. enthalten. In verschiedenen Domänen können die Geschäftsregeln auch unterschiedlich sein, sodass ich meine gekapselt habe Spät gebundene Validierungslogik in einer Validate-Methode, die der Basisklasse meiner Datenübertragungsobjekte zugeordnet ist. Hoffe das macht Sinn :)
quelle
Ein Fall, in dem Erweiterungsmethoden sehr nützlich waren, war eine Clientanwendung, die ASMX-Webdienste verwendet. Aufgrund der Serialisierung enthalten die Rückgabetypen von Webmethoden keine Methoden (nur die öffentlichen Eigenschaften dieser Typen sind auf dem Client verfügbar).
Mithilfe von Erweiterungsmethoden konnten Funktionen (auf der Clientseite) zu den von Webmethoden zurückgegebenen Typen hinzugefügt werden, ohne dass ein weiteres Objektmodell oder zahlreiche Wrapper-Klassen auf der Clientseite erstellt werden müssen.
quelle
Erweiterungsmethoden können verwendet werden, um eine Art Mixin in C # zu erstellen .
Dies bietet wiederum eine bessere Trennung der Bedenken für orthogonale Konzepte. Schauen Sie sich diese Antwort als Beispiel an.
Dies kann auch verwendet werden, um Rollen in C # zu aktivieren , einem Konzept, das für die DCI-Architektur von zentraler Bedeutung ist .
quelle
Denken Sie auch daran, dass Erweiterungsmethoden hinzugefügt wurden, um die Lesbarkeit der Linq-Abfrage zu verbessern, wenn sie in ihrem C # -Stil verwendet wird.
Diese beiden Affekte sind absolut gleichwertig, aber der erste ist weitaus besser lesbar (und die Lücke in der Lesbarkeit würde sich natürlich mit mehr verketteten Methoden vergrößern).
Beachten Sie, dass die vollständig qualifizierte Syntax sogar wie folgt lauten sollte:
Zufällig müssen die Typparameter von
Where
undLast
müssen nicht explizit erwähnt werden, da sie dank des Vorhandenseins des ersten Parameters dieser beiden Methoden abgeleitet werden können (der Parameter, der durch das Schlüsselwort eingeführt wirdthis
und sie zu Erweiterungsmethoden macht).Dieser Punkt ist offensichtlich (unter anderem) ein Vorteil der Erweiterungsmethoden, und Sie können ihn in jedem ähnlichen Szenario nutzen, in dem es um die Verkettung von Methoden geht.
Insbesondere ist es die elegantere und überzeugendere Art, eine Basisklassenmethode zu finden, die von jeder Unterklasse aufgerufen werden kann und einen stark typisierten Verweis auf diese Unterklasse (mit dem Unterklassentyp) zurückgibt.
Beispiel (ok, dieses Szenario ist total kitschig): Nach einer guten Nacht öffnet ein Tier die Augen und schreit dann; Jedes Tier öffnet die Augen auf die gleiche Weise, während ein Hund bellt und eine Ente kwaks.
Konzeptionell
OpenTheEyes
sollte es sich um eineAnimal
Methode handeln, die jedoch eine Instanz der abstrakten Klasse zurückgibtAnimal
, die bestimmte Unterklassenmethoden wieBark
oderDuck
oder was auch immer nicht kennt . Die 2 als * 1 und * 2 kommentierten Zeilen würden dann einen Kompilierungsfehler auslösen.Dank der Erweiterungsmethoden können wir jedoch eine Art "Basismethode haben, die den Unterklassentyp kennt, auf dem sie aufgerufen wird".
Beachten Sie, dass eine einfache generische Methode die Arbeit hätte erledigen können, aber auf eine viel umständlichere Weise:
Diesmal kein Parameter und damit keine mögliche Rückgabe des Rückgabetyps. Der Anruf kann nichts anderes sein als:
... was den Code sehr wiegen kann, wenn mehr Verkettung erforderlich ist (insbesondere in dem Wissen, dass der Typparameter immer in
<Dog>
Goofys Zeile und<Duck>
in Donalds Zeile steht ...)quelle
Ich kann nur ein Wort dazu sagen: WARTUNGSFÄHIGKEIT Dies ist der Schlüssel für die Verwendung von Erweiterungsmethoden
quelle
Ich denke, Erweiterungsmethoden helfen dabei, Code zu schreiben, der klarer ist.
Anstatt eine neue Methode in Ihre Klasse einzufügen, wie Ihr Freund vorgeschlagen hat, fügen Sie sie in den ExtensionMethods-Namespace ein. Auf diese Weise erhalten Sie ein logisches Ordnungsgefühl für Ihre Klasse. Methoden, die sich nicht direkt mit Ihrer Klasse befassen, werden sie nicht überladen.
Ich bin der Meinung, dass Erweiterungsmethoden Ihren Code klarer und besser organisiert machen.
quelle
Es ermöglicht Ihrem Editor / Ihrer IDE, Vorschläge automatisch zu vervollständigen.
quelle
Ich liebe sie für das Erstellen von HTML. Häufig gibt es Abschnitte, die wiederholt verwendet oder rekursiv generiert werden, wenn eine Funktion nützlich ist, aber sonst den Programmfluss unterbrechen würde.
Es gibt auch Situationen, in denen ein Objekt eine benutzerdefinierte Logik benötigt, um für HTML-Ausgabeerweiterungsmethoden vorbereitet zu werden. Mit dieser Funktion können Sie diese Funktionalität hinzufügen, ohne Präsentation und Logik innerhalb der Klasse zu mischen.
quelle
Ich habe festgestellt, dass Erweiterungsmethoden nützlich sind, um verschachtelte generische Argumente abzugleichen.
Das klingt etwas seltsam - aber sagen wir, wir haben eine generische Klasse
MyGenericClass<TList>
und wir wissen, dass TList selbst generisch ist (z. B. aList<T>
). Ich glaube nicht, dass es eine Möglichkeit gibt, dieses verschachtelte 'T' ohne eine der beiden Erweiterungen aus der Liste zu entfernen Methoden oder statische Hilfsmethoden. Wenn wir nur statische Hilfsmethoden zur Verfügung haben, ist dies (a) hässlich und (b) zwingt uns, die in der Klasse enthaltenen Funktionen an einen externen Speicherort zu verschieben.Um beispielsweise die Typen in einem Tupel abzurufen und in eine Methodensignatur umzuwandeln, können wir Erweiterungsmethoden verwenden:
Ich bin mir jedoch nicht sicher, wo die Trennlinie liegen soll - wann sollte eine Methode eine Erweiterungsmethode sein und wann sollte sie eine statische Hilfsmethode sein? Irgendwelche Gedanken?
quelle
Ich habe Eingabezonen auf meinem Bildschirm und alle müssen ein Standardverhalten implementieren, unabhängig von ihrem genauen Typ (Textfelder, Kontrollkästchen usw.). Sie können keine gemeinsame Basisklasse erben, da jeder Typ der Eingabezone bereits von einer bestimmten Klasse (TextInputBox usw.) abgeleitet ist.
Vielleicht könnte ich durch Aufsteigen in der Vererbungshierarchie einen gemeinsamen Vorfahren wie WebControl finden, aber ich habe die Framework-Klasse WebControl nicht entwickelt und sie enthüllt nicht, was ich brauche.
Mit der Erweiterungsmethode kann ich:
1) Erweitern Sie die WebControl-Klasse und erhalten Sie dann mein einheitliches Standardverhalten für alle meine Eingabeklassen
2) Alternativ können Sie alle meine Klassen von einer Schnittstelle ableiten, z. B. IInputZone, und diese Schnittstelle mit Methoden erweitern. Ich kann jetzt Erweiterungsmethoden für die Schnittstelle in allen meinen Eingabezonen aufrufen. Ich habe so eine Art Mehrfachvererbung erreicht, da meine Eingabezonen bereits von mehreren Basisklassen abgeleitet sind.
quelle
Es gibt so viele großartige Beispiele für Erweiterungsmethoden, insbesondere für IEnumerables, wie oben beschrieben.
zB wenn ich eine
IEnumerable<myObject>
habe kann ich eine Methode erstellen und erweitern fürIEnumerable<myObject>
... die Liste erstellen
Ohne Erweiterung müssten Methoden aufrufen:
Ein weiteres gutes Beispiel ist das blitzschnelle Erstellen einer zirkulären verknüpften Liste!
Ich kann es gutschreiben!
kreisförmig verknüpfte Liste mit Erweiterungsmethoden
Kombinieren Sie diese nun und verwenden Sie den Code für Erweiterungsmethoden wie folgt.
eher, als
Verwenden von Erweiterungsmethoden Es ist übersichtlicher und leichter zu lesen und objektorientierter. auch ganz in der Nähe von:
Zeigen Sie das Ihrem Kollegen! :) :)
quelle