Erweiterungsmethoden und ihre Implikationen im Software Engineering (oder ist das wirklich eine gute Idee?) [geschlossen]

8

Richtig, also führt MS Erweiterungsmethoden für C # 3.0 ein. Im Grunde erlaubt es Ihnen, neue Methoden zu einer bestehenden Klasse hinzuzufügen, ohne daraus eine Unterklasse zu erstellen oder die Implementierung zu ändern. Sofort gehen mir die Alarmglocken durch.

1) Sie beginnen mit der Implementierung eigener Erweiterungsmethoden für eine Bibliothek oder Standardbibliotheksklassen. Jetzt ist es nicht mehr standardisiert.

2) In OOP definieren Sie einen neuen Typ entweder durch Vererbung oder Komposition. Was ist eigentlich Erweiterungsmethoden? Ebenso ist bei der Verwendung von Erweiterungsmethoden keine explizite Beziehung definiert.

3) Sind Erweiterungsmethoden zwischen Projekten übertragbar? Was ist, wenn zwei Erweiterungsmethoden für eine Methode existieren?

Also sind Erweiterungsmethoden eine ganze Reihe von Würmern, die es zu vermeiden lohnt? Ich kann sehen, dass es Verdienste gibt, wie Sie weniger tippen, aber irgendwie sieht es so aus, als würde es zu einer schlechten Übung führen.

Meinungen?

    
Extrakun 27.07.2009, 06:22
quelle

7 Antworten

9

Erweiterungsmethoden sind nicht zu einem Typ hinzugefügt. Sie sind nur syntaktischer Zucker. Du kannst nicht auf private Sachen zugreifen. Eine Erweiterungsmethode ist wie jede statische Methode, die einen Typ verwendet.

Das Schlimmste, was sie tun können, ist Lesbarkeit zu beeinträchtigen und Menschen irrezuführen. Jenseits der Syntax sind sie nicht existent.

UPDATE (re comment):

Genau das meinte ich mit "irreführenden Menschen" und "Lesbarkeitsschäden". Glücklicherweise ist Visual Studio bei der Unterscheidung von Erweiterungsmethoden sehr hilfreich (mit einem Symbol in der IntelliSense-Liste und dem Tooltip). Persönlich bin ich ein wenig voreingenommen dagegen, eine Reihe von Erweiterungsmethoden zu beliebigen Klassen des Frameworks hinzuzufügen (mit Ausnahme von sealed classes, wo Erweiterungsmethoden sehr sinnvoll sein können), sofern sie nicht zur Verfügung stehen ein signifikanter Vorteil für das jeweilige Projekt. Ich bevorzuge es, Erweiterungsmethoden hauptsächlich für Schnittstellen und Klassen auf den obersten Ebenen der Vererbungshierarchie zu halten. Dadurch werden Entwickler sie nur dort verwenden, wo sie in vielen Fällen im Framework anwendbar sind, anstatt jede Hilfsmethode zu einer Erweiterung zu machen (IMO, dies ist ein direktes Artefakt der Autodiscovery von Erweiterungsmethoden in einem ganzen Namespace. Ich wünschte wirklich, dass C # hinzugefügt werden müsste eine using -Direktive für eine spezifische class , anstatt automatisch alle Erweiterungen in namespace ) zu importieren.

Meiner Erfahrung nach ist es selten ein Wartungsproblem, wenn Sie die Erweiterungsmethoden nicht überbeanspruchen, indem Sie jede Hilfsmethode, die einige Male benutzt wird (ich habe schon einige Leute dies gesehen), eine Erweiterung machen. Es verbessert die Lesbarkeit, wenn es sinnvoll eingesetzt wird.

Es ist keine gute Sache, Klassen mit Erweiterungsmethoden aufzuräumen. In extremen Fällen kann es gefährlich sein. Man könnte ein Name Kollision Problem einführen, indem man eine Methode zur Klasse mit dem gleichen Namen einer bereits existierenden Erweiterung hinzufügt. Dies kann Code-Snippets unterbrechen, die zuvor die Erweiterung aufgerufen haben und jetzt die neue Methode aufrufen.
Meiner Meinung nach ist dies das größte Problem, das mit Erweiterungsmethoden verbunden ist. Dies macht eine gute Benennung von Erweiterungen sehr wichtig.

    
Mehrdad Afshari 27.07.2009, 06:28
quelle
5

Extension-Methoden modifizieren die existierende Klasse überhaupt nicht, sie sind nur "syntaktischer Zucker" oder ein Compiler-Trick, um eine statische Methode an eine Klasse anzuhängen. Sie können das gleiche Ziel erreichen, indem Sie einfach eine normale statische Hilfsmethode in einer anderen Klasse erstellen, die die gewünschte Klasse als erstes Argument der Methode verwendet. Ich sehe Ihren Punkt darin, Methoden zu einer Klasse hinzuzufügen und dadurch zu entstandardisieren, aber das ist nicht wirklich, was passiert, und ich finde tatsächlich, dass Erweiterungsmethoden intuitiv und praktisch sind, um einer bestehenden Klasse domänenspezifische oder Hilfsmethoden hinzuzufügen das wäre sonst unveränderbar.

    
Andy White 27.07.2009 06:29
quelle
5

Nein, es ist keine Dose Würmer, die es zu vermeiden lohnt. Es kann das Leben viel einfacher machen, und IMO ermöglicht es Ihnen, die Kernoperationen des Typs von "Helfer" -Methoden zu trennen, die ausschließlich von diesen Kernoperationen implementiert werden können. Ich war versucht, Erweiterungsmethoden auf diese Weise zu verwenden, selbst wenn sie nicht wirklich notwendig sind (dh ich hatte eine Basisklasse, in die ich sie einfügen konnte, und ich habe die Kontrolle über den Code ).

Sie müssen wissen, dass Erweiterungsmethoden nur sind, damit statische Methodenaufrufe wie Instanzmethoden aussehen, wenn der entsprechende Namespace mit den Erweiterungsmethoden importiert wird. Insbesondere:

  • Es fügt keine Methoden zu einem Typ hinzu, so dass es keine Standardbibliotheken "nicht standardisiert" macht. Es bedeutet nur, dass Sie, wenn Sie die Erweiterungsmethoden zur Verfügung haben, in der Lage sind, leichter mit diesen Bibliotheken zu arbeiten.
  • There ist eine explizite Beziehung, die mit Erweiterungsmethoden definiert ist: Die Erweiterungsmethode deklariert, welchen Typ sie mit dem Typ des ersten Parameters "erweitert". Es ist keine Zusammensetzung oder Aggregation, aber ich sehe nicht, warum das ein Problem ist. Wenn etwas nützlich ist und das Design nicht wirklich schlechter macht, ist es dann wichtig, ob es Teil eines traditionellen OO ist?
  • Ja, Erweiterungsmethoden sind zwischen Projekten übertragbar. Wie immer gibt es Regeln dafür, was passiert, wenn zwei Erweiterungsmethoden mit demselben Namen gleichzeitig sichtbar sind.

Erweiterungsmethoden über Schnittstellen sind sehr nett, was eine einfache Methodenverkettung usw. erlaubt. Ich würde eher einen Aufruf der Erweiterungsmethode als einen expliziten statischen Aufruf wie in Java sehen:

%Vor%

Ein paar Nachteile allerdings:

  • Es ist nicht möglich, dass abgeleitete Typen die Implementierung effizienter überschreiben. Natürlich kann der abgeleitete Typ eine Methode mit der gleichen Signatur deklarieren, die aber nur verwendet wird, wenn der Typ der Kompilierungszeit angemessen ist.
  • Die Art, in der Erweiterungsmethoden in C # entdeckt werden, ist ein Schmerz. Ich habe darüber woanders geschimpft ...
  • Erweiterungsmethoden sind nicht verfügbar, wenn dynamisches Schreiben verwendet wird.

Insgesamt finde ich, dass sie sehr schön sind - und wenn sie in Maßen verwendet werden, können sie den Unterschied ausmachen. Ich würde sicherlich nicht LINQ ohne sie verwenden wollen.

    
Jon Skeet 27.07.2009 06:28
quelle
5

Sie können die Alarmglocken ausschalten. Erweiterungsmethoden machen nur einen sehr kleinen Unterschied zur Syntax und nichts anderes. Anstatt zu schreiben:

%Vor%

Sie schreiben:

%Vor%

Es tauscht einfach die Reihenfolge aus und eliminiert den Klassennamenqualifikator. Ansonsten ist es identisch. Der Wert davon ist, dass Sie einen Variablennamen eingeben können und die IDE Ihnen nützliche Methoden in der IntelliSense-Funktion vorschlagen kann, und Sie können den Code von links nach rechts lesen, so dass "verschachtelte" Funktionsaufrufe viel besser lesbar werden. p>

Alle Ihre Bedenken gelten gleichermaßen für statische Methoden - und es lohnt sich nicht, sich darum zu kümmern.

Aktualisieren

Müssen Erweiterungsmethoden "vorgeben, Magie zu wirken"? Nur wenn du denkst, etwas Syntax umzutauschen, ist Magie!

Es ist wahrscheinlicher, dass Sie einfach daran gewöhnt sind, Dinge auf eine bestimmte Art geschrieben zu sehen, und so überrascht es Sie, sie "rückwärts" geschrieben zu sehen. Aber aus der Perspektive anderer Sprachen ist es jetzt der richtige Weg.

Einige Sprachen erlauben es, jede Nicht-Instanz-Methode optional mit dem ersten Argument vor dem Methodennamen zu schreiben, und wenn Sie den Punkt weglassen, dann ist dies eine nette Möglichkeit, Infix-Operatoren wie a + b zu unterstützen, ohne etwas Besonderes tun zu müssen .

Eine Instanzmethode ist eine Möglichkeit, diese Syntax zu aktivieren, aber wenn Sie darauf verzichten wollten, warum brauchen Sie nicht, dass Instanzmethoden so aufgerufen werden, um wirklich konsistent zu sein?

%Vor%

Das ist ähnlich wie bei F #. Schließlich kann eine Instanzmethode von string als mit einem ersten Parameter vom Typ string angesehen werden. Sie betrachten es normalerweise nicht als Parameter, aber es funktioniert in etwa gleich, und die einheitliche Syntax hat Vorteile.

Eine Instanzmethode hat Zugriff auf die privaten Mitglieder der Klasse, in der sie definiert ist, während dies bei einer Erweiterungsmethode nicht möglich ist. Eine Instanzmethode in einer abgeleiteten Klasse hat jedoch keinen Zugriff auf die privaten Daten der Basisklasse. Und auf jeden Fall, warum sollte der Anrufer sich darum kümmern?

Vorbehalte

Ich möchte nicht den Eindruck erwecken, dass alle Anwendungen von Erweiterungsmethoden sinnvoll sind. Gibt es zum Beispiel gute Gründe, eine Erweiterungsmethode für object oder eine generische Erweiterungsmethode für den unbeschränkten Typ T ? Solche Dinge würden von Intellisense in fast jedem Kontext vorgeschlagen und würden zu Spracherweiterungen, z.B. Mit .

Dann gibt es die Debatte darüber, ob eine Erweiterungsmethode ihr erstes Argument null zulässt. Persönlich denke ich, dass es in Ordnung ist, solange der Name der Methode dies klar macht, also denke ich, dass string.IsNullOrEmpty als Verlängerungsmethode in Ordnung wäre. Aber andere sind militanter und es ist mir egal, also würde ich eine "wenn in Rom" Haltung einnehmen. Hier ist ein anderes Beispiel:

%Vor%

Der Name macht deutlich, dass es einen Null-Check beinhaltet (das ist der Sinn).

    
Daniel Earwicker 27.07.2009 06:29
quelle
2

Ich betrachte es als eine bequeme Möglichkeit, das Decorator-Muster zu implementieren. Mit Erweiterungsmethoden können Sie einen Typ erweitern, indem Sie ihm Methoden hinzufügen. Natürlich sind sie zwischen Projekten portierbar, wenn Sie Ihre Erweiterungsklassen in einer separaten Assembly haben, die Sie teilen können.

    
tranmq 27.07.2009 06:32
quelle
1

Ich wollte mit einem Punkt, den Sie gesagt haben, ein kleines Problem ansprechen. Erweiterungsmethoden erlauben es nicht, Methoden zu einer vorhandenen Klasse hinzuzufügen. Sie ermöglichen es Ihnen, das Aussehen einer Methode zu einer vorhandenen Klasse hinzuzufügen. Die Unterscheidung ist subtil, aber sehr signifikant.

Jetzt, um gegen die Punkte zu gehen, die du gemacht hast

  1. Ich glaube nicht, dass das wahr ist. An der Standardisierung der Bibliothek hat sich nichts geändert. Personen, die Ihre Erweiterungsmethoden verwenden, sehen eine Erweiterung der Bibliothek. Ob es den Standard der Bibliothek ändert oder nicht, hängt stark davon ab, was Sie in Ihren Methoden tun.

  2. Es ist einfach eine Möglichkeit, einen Typ mit Methoden zu erweitern, ohne den ursprünglichen Vertrag zu ändern.

  3. Ich bin nicht sicher, was Sie mit portable meinen, aber es hängt wahrscheinlich stark von Ihrer Implementierung ab. Wenn zwei Erweiterungsmethoden mit demselben Namen existieren, werden sie eine Überladungsauflösung durchlaufen, und Fehler werden entsprechend erhöht.

Das Verwenden und Definieren von Erweiterungsmethoden ist einfach syntaktischer Zucker für statische Methoden. Es erlaubt mir, einen Typ für das Fehlen eines besseren Wortes mit Methoden anzupassen, die spezifisch für meine Problemdomäne sind oder einfach etwas sind, das sonst im ursprünglichen Framework fehlt ( IEnumerable<T>.ForEach for example ).

Ich finde kein Argument ihrer Bosheit als zwingend und deshalb werde ich sie weiterhin benutzen, weil ich sie produktiv finde.

    
JaredPar 27.07.2009 06:30
quelle
1

Andere haben bereits darauf hingewiesen, dass Erweiterungsmethoden den Originaltyp nicht ändern, also nur ein bisschen hinzufügen: Beachten Sie, dass die Erweiterungsmethoden nur sichtbar sind, wenn Sie den definierenden Namensraum importieren. Wenn Sie also einige Methoden zur Zeichenfolge hinzufügen, werden sie nur verfügbar, wenn Sie diese explizit anfordern. Mit anderen Worten, der Umfang der Erweiterungsmethoden kann kontrolliert werden. Vielleicht nicht perfekt, aber sie erscheinen nicht einfach aus dem Nichts, wenn jemand sie zu einem Projekt hinzufügt.

    
Brian Rasmussen 27.07.2009 06:49
quelle

Tags und Links