mehr Vorteile oder Nachteile zu delegieren, die Mitglieder über die klassischen Funktionen?
class my_class
{
public int add_1(int a, int b) {return a + b;}
public func<int, int, int> add_2 = (a, b) => {return a + b;}
}
add_1 ist eine Funktion in der Erwägung, dass add_2 ein Delegierter. Allerdings ist in diesem Zusammenhang die Delegierten können forfill eine ähnliche Rolle.
Wegen Präzedenzfall und das design der Sprache ist die Standard-Wahl für C# müssen Methoden Funktionen.
Jedoch beide Ansätze haben vor-und Nachteile, so dass ich produziert habe eine Liste. Gibt es noch mehr Vorteilen oder Nachteilen der beiden Ansätze?
Vorteile zu herkömmlichen Methoden.
- mehr konventionelle
- Benutzer von außen die Funktion finden Sie unter benannte Parameter - für die add_2 syntax arg_n und eine Art ist in der Regel nicht genug Informationen.
- funktioniert besser mit intellisense - ty Minitech
- arbeitet mit Reflexion - ty Minitech
- arbeitet mit erbschaft - ty Eric Lippert
- hat "dieses" - ty CodeInChaos
- geringere Gemeinkosten, Geschwindigkeit und Speicher - ty Minitech und CodeInChaos
- brauchen nicht zu denken über public\private in Bezug auf die beiden ändern und mit der Funktion. - ty CodeInChaos
- weniger dynamisch, weniger ist erlaubt, dass zur Kompilierzeit nicht bekannt - ty CodeInChaos
Vorteile "Feld der delegate-Typ" - Methoden.
- mehr im Einklang, nicht member-Funktionen und Daten-member, es ist nur einfach alle Daten der Mitglieder.
- können äußerlich Aussehen und Verhalten sich wie eine variable.
- speichern Sie es in einem container funktioniert gut.
- mehrere Klassen nutzen könnte, die gleiche Funktion, als ob es wurden jeweils diejenigen member-Funktion ist, wäre dies sehr allgemein, präzise und haben gute Wiederverwendung von code.
- einfach, überall zu verwenden, zum Beispiel als lokale Funktion.
- vermutlich funktioniert gut, wenn übergeben, um mit garbage collection.
- mehr Dynamik, weniger bekannt sein muss zur compile-Zeit, zum Beispiel könnte es sein, Funktionen, konfigurieren Sie das Verhalten der Objekte zur Laufzeit.
- als ob die Kapselung ist es code, kombiniert und überarbeitet, msdn.microsoft.com/en-us/library/ms173175%28v=vs.80%29.aspx
- Benutzer außerhalb der Funktion sehen Unbenannte Parameter - manchmal ist das hilfreich, obwohl es schön wäre, um in der Lage sein, Sie zu benennen.
- kann kompakter sein, in diesem einfachen Beispiel wird zum Beispiel die Rückgabe beseitigt werden könnten, wenn es ein parameter die Klammern könnten auch entfernt werden.
- roll ' r eigenen Verhaltensweisen wie Vererbung - ty Eric Lippert
- anderen überlegungen wie der funktionale, modulare, verteilte, (code zu schreiben, zu testen oder Argumentation über code) etc...
Bitte nicht die Abstimmung zu schließen, das ist schon passiert und hab es wieder geöffnet. Es ist eine berechtigte Frage, auch wenn Sie glaube nicht, dass die Delegierten Ansatz hat viele praktische Nutzung gegeben, wie Sie Konflikte mit etablierten coding style oder Sie nicht wie den Vorteilen der Delegierten.
- Sind Sie sich bewusst, dass das zweite Beispiel ist nicht eine Funktion? Es ist ein Delegierter.
- Wenn Sie zurückkehren möchten ungültig, dann verwenden Sie
Action<>
stattFunc<>
- Wo hast du diesen angeboten eine Wahl?
- Ein Beispiel, warum das schrecklich ist? my_class a = new my_class(); ein.add_2 = null; ein.add_2(1, 2); ----- NullReferenceException! AHHHH!
- Ich verstehe nicht, warum das geschlossen wurde. Es ist ein absolut vernünftig Frage über die konkurrierenden Faktoren in der Gestaltung von details der Implementierung der Klasse. ich Häufig verwenden diese Technik in meinen eigenen Programmen, weil es echte Vorteile -- nämlich, dass es mir erlaubt, sehr leicht zu entscheiden, welche Methoden in einer Funktion haben memoization angewendet.
- Ein Delegat umschließt eine Funktion.
- So verwenden Sie die
readonly
keyword, oder eineprivate
setter. - Ich Stimme zu, dass es eine gute und interessante Frage. Aber wohl nicht erfüllen, die ALSO die Richtlinien. Fragen dieser Art führen zu Diskussion, subjektive Antworten, und teilweise Antworten, die qualifiziert Sie für eine Schließung.
- Warum sollten Sie so etwas tun, nur um eine Funktion schreiben, das wird jeder machen, der das guckt Ihr verbringen Monate in verstehen WARUM
- Ich möchte vermeiden, der zweite für öffentliche Mitglieder. Für interne code kann es sinnvoll sein (insbesondere, wenn
static readonly
) . - Es sei denn, Sie haben sich die Delegierten mit aller Regelmäßigkeit. Oder Javascript, in der die Methoden definiert sind, die in ganz der gleichen Weise.
- ja 🙂 in der Tat. Schreckliche Weise, um code zu schreiben aus meiner Sicht.
- Wenn Sie tatsächlich setzen die Delegierten, Sie können dicht über den Gegenwert von
this
, und Sie erhalten die gleiche Vorteil. - Meine größte Sorge zu diesem code, und die Art und Weise die Frage beantwortet wurde, ist das Gefühl, dass der OP meint, dass die beiden gleichwertig sind, wie Sie sein würde, wenn dies JavaScript.
- Ich denke, Javascript ist keine option 1, da kann man wieder einsetzen, "Methoden", und alle Aufrufe werden Laufzeit dynamisch. Zu sehen, dass er bekam eine etwas genaue und ansehnliche Liste von pros und cons, ich bin nicht sicher, ob die OP fehlt nichts, außer vielleicht die Angst gegen den grain und verliert einige perf/Sicherheit 🙂 Wenn Sie möchten, dass einige Validierung von Menschen zu beantworten, obwohl die Benutzer solcher code (das ersetzt jede Methode, die mit option 2) wäre sehr überrascht, und vielleicht Sauer ist, da es möglicherweise wegspülen eine Menge von Werkzeugen und perf für potenziell wenig Verstärkung.
- JavaScript hat Methoden, nicht nur Klassen. Und was die OP fehlt, ist, dass die Vorteile für Methode 2 sind nicht wichtig, außer in einem winzigen Bruchteil der Fälle. Die Frage gestellt wird, als ob die beiden vielleicht äquivalent: sind Sie nicht, es sei denn, Sie sind verpflichtet, tun, lösen einen kleinen fcaction der Fälle.
- Ich bezweifle, dass eine funktionale Programmierer, wie Sie Ihre öffentlichen veränderlichen Feld.
- Feste CodeInChaos. Ich dachte an die Verwendung von Funktionen als Parameter an Funktionen und solche, aber probbably, havn ' T viel getan, funktional. Ich getroffen habe, dass line-out, wenn Sie denken, ein Weg, der auch etwas ähnlich, aber wahr, ich werde es anstelle 😛
- Aktuelle version der Antwort: ich denke, dass eric erwähnt überlastung, nicht die Vererbung. Sie können auch verwenden die Delegierten void zurück - nutzen Sie einfach
Action
stattFunc
wie @Hogan erwähnt. - Die Abstimmung zu schließen. Siehe Ben Voight ' s Kommentar. Ich mag die Antworten auf diese Frage, aber die Art und Weise es wird gebeten, erfordert eine subjektive Antwort. SO Fragen sollten nie einfach Fragen für weitere Diskussion, und das sollten Sie auch nicht sein, die Eimer zu werfen, Daten in. Mit dem Eimer ist nützlich, Sie sollten aber nicht die wichtigste Frage. SO Fragen sollte Fragen für eine definitive Antwort für eine bestimmte Frage. Einer Weise zu formulieren, diese Frage, um eine Objektive Antwort (das ist die Frage, die fast alle beantwortet, obwohl es gar nicht gefragt): "Warum würde jemand ersetzen Sie jede Methode-definition mit einer delegieren?"
- Ich habe mir vor kurzem aktualisiert die Einführung der Frage Merlyn. Aber nicht, wie Sie vorgeschlagen, wie es scheint, eine sehr einseitige Art zu Fragen es. Beachten Sie auch, dass es schon geschlossen, bevor und schnell wieder geöffnet wird. ty Hogan, ich habe gerade sanktioniert dein Kommentar.
Du musst angemeldet sein, um einen Kommentar abzugeben.
First off, das "high-order bit" für mich mit Bezug auf diese design-Entscheidung sein würde, dass würde ich nie tun diese Art der Sache mit einem öffentlichen Feld/Methode. Zumindest würde ich eine Eigenschaft, und wahrscheinlich nicht einmal das.
Für private Felder, benutze ich dieses Muster ist relativ Häufig, in der Regel wie diese:
und jetzt kann ich sehr einfach testen Sie die Leistungs-Merkmale der verschiedenen memoization Strategien, die zimmerreserviereung, ohne das Sie den text ändern, der von ActualFunction überhaupt.
Weiterer Vorteil des "Methoden-Felder der delegate-Typ" - Strategie, die Sie implementieren können code-sharing-Techniken, die anders sind als die, die wir haben "gebacken", um die Sprache. Einen geschützten Bereich der Delegaten-Typ ist im wesentlichen ein virtuelle Methode, aber mehr flexibel. Abgeleitete Klassen können ersetzen Sie es mit was Sie wollen, und Sie haben emuliert einen regelmäßigen virtuellen Methode. Aber könnten Sie bauen benutzerdefinierte inheritence Mechanismen; wenn Sie wirklich, wie die prototype-Vererbung, zum Beispiel, Sie könnten eine Konvention, dass, wenn das Feld null ist, dann eine Methode auf einige prototypische Instanz aufgerufen wird, statt, und so weiter.
Einen großen Nachteil der Methoden-sind-fields-of-delegate-Ansatz ist, dass natürlich eine überlastung nicht mehr funktioniert. Felder müssen eindeutig sein name; Methoden lediglich eindeutig sein müssen in der Signatur. Auch, Sie nicht bekommen, generische Felder, die Art und Weise, dass wir generische Methoden, also Verfahren Typrückschluss funktioniert.
Invoke
Methoden. Es könnte tatsächlich funktionieren, außer leider ist C# nicht die Arbeit mit Delegierten syntax und erfordert.Invoke
genannt werden, die explizit für diese Klasse...Die zweite, meiner Meinung nach, bietet einen absolut keine Vorteil gegenüber der ersten. Es ist viel weniger lesbar, ist wahrscheinlich weniger effizient (da
Invoke
hat implizit) und ist nicht mehr präzise an alle. Was mehr ist, wenn Sie jemals verwenden Sie reflektion, es wird nicht zeigen sich als eine Methode, wenn Sie so tun, dass Sie Ihre Methoden in jeder Klasse, die Sie vielleicht etwas zu brechen, die scheint, wie es funktionieren sollte. In Visual Studio, IntelliSense nicht auf eine Beschreibung der Methode, da Sie keine XML-Kommentare Delegierten (zumindest nicht in der gleichen Weise würden Sie legte Sie auf, normal Methoden) und Sie wissen nicht, was Sie zeigen sowieso, es sei denn, es ist readonly (aber was ist, wenn der Konstruktor geändert?) und es wird zeigen, wie ein Feld, keine Methode, das ist verwirrend.Die einzige Zeit, die Sie sollten wirklich lambdas ist in den Methoden, bei denen Sperrungen erforderlich werden, oder wenn es ' s bietet Ihnen einen erheblichen Komfort-Vorteil. Ansonsten, du bist nur eine Verringerung der Lesbarkeit (im Grunde die Lesbarkeit meiner ersten Absatz gegenüber dem aktuellen one) und dass die Kompatibilität mit früheren Versionen von C#.
+
Betreiber ist mehr als nützlich, die=
Zuordnung., Warum Sie sollten es vermeiden, die Delegierten als Methoden standardmäßig, und was sind die alternativen:
Lernkurve
Verwendung von Stellvertretern diese Weise überrascht eine Menge Leute. Nicht jeder kann wickeln Sie Ihren Kopf um die Delegierten, oder warum würden Sie wollen, um die swap-Funktionen. Es scheint eine Lernkurve. Wenn man einmal Vergangenheit, die Delegierten scheinen einfach.
Perf und Zuverlässigkeit
Gibt es einen performance-Verlust zu Delegaten aufrufen, auf diese Weise. Dies ist ein weiterer Grund, warum ich standardmäßig die traditionelle Methode der Erklärung, es sei denn, es aktiviert etwas in mein Muster.
Gibt es auch eine Ausführung Frage der Sicherheit. Öffentliche Felder null-Werte zulassen. Wenn Sie übergeben eine Instanz einer Klasse, die mit einem öffentlichen Bereich, den Sie haben zu prüfen, dass es nicht null ist, bevor Sie es. Das schmerzt perf und ist irgendwie lahm.
Können Sie umgehen, indem Sie in allen öffentlichen Bereichen auf Eigenschaften (das ist in der Regel in allen .Net-coding-standards sowieso). Dann in den setter-Wurf ein
ArgumentNullException
wenn jemand versucht, zu ordnennull
.Programm-design
Selbst wenn man mit all dem umzugehen, so dass Methoden, die in der veränderlichen überhaupt geht gegen eine Menge von dem design für statische OO und funktionalen Programmiersprachen.
In statische OO-Typen sind immer statische und dynamische Verhalten wird aktiviert durch Polymorphismus. Sie kennen die genauen Verhalten eines Typs basiert auf seinen Laufzeit-Typ. Dies ist sehr hilfreich beim Debuggen eines vorhandenen Programms. Ermöglichen Sie Ihrem Typen geändert werden, die zur Laufzeit schädigt diese.
Statisch OO und Funktion Programmier-Paradigmen, zu begrenzen und zu isolieren Nebenwirkungen ist sehr hilfreich, und mit voll unveränderlich Strukturen ist eine der wichtigsten Möglichkeiten, dies zu tun. Der einzige Punkt der Freilegung Methoden als Delegierte zu erstellen veränderliche Strukturen, die das genaue Gegenteil bewirken.
Alternativen
Wenn Sie wirklich wollten, so weit zu gehen, wie immer Delegierten zu ersetzen Methoden, sollten Sie eine Sprache verwenden, wie IronPython oder etwas anderes gebaut auf der Oberseite des DLR. Diese Sprachen werden nachgerüstet und abgestimmt für den Paradigmenwechsel, den Sie versuchen zu implementieren. Benutzer und Verwalter deines Codes nicht Wundern.
Dass gesagt wird, es sind Verwendungen, rechtfertigen die Verwendung von Stellvertretern, die als Ersatz für Methoden. Sie sollten nicht erwägen diese option, es sei denn, Sie haben einen zwingenden Grund, dies zu tun, der überschreibt diese Leistung, Verwirrung, Zuverlässigkeit und design-Fragen. Sie sollten dies nur tun, wenn Sie bekommen etwas zurück.
Verwendet
Für private Mitglieder, Eric Lippert ' s Antwort beschreibt eine gute Verwendung: (Memoization).
Können Sie es verwenden, um implementieren eines Strategie-Musters in eine Funktion-basierte Art und Weise, anstatt dass eine Klasse Hierarchie. Wieder, die ich verwenden würde, private Mitglieder, die für dieses...
...Beispiel-code:
...Dies ist besonders nützlich in automatisierten Integrationstests, wo Sie eine Menge von setup/tear down. In solchen Fällen ist es oft sinnvoll, die keep state -, die in einer Klasse entwickelt, um Kapseln, die Muster, anstatt verlassen sich auf die unit-test-Vorrichtung. Auf diese Weise können Sie leicht Unterstützung für das teilen von Skelett in der test-suite zwischen den Leuchten, ohne sich auf (manchmal schlechten) test-fixture-Vererbung. Es könnte auch eher für die Parallelisierung, abhängig von der Implementierung der tests.
Intellisense-Unterstützung
Benannten Delegierten - ich glaube, das bekommen Sie zumindest einige Intellisense für die Parameter (wahrscheinlich nur die Namen, weniger wahrscheinlich, XML-docs - bitte korrigieren Sie mich, wenn ich falsch Liege):
ArgumentNullException
es. Ich passe meine Antwort zu empfehlen, und wieder aus dem "immer überprüfen" - Anweisung.Ich möchte vermeiden, delegieren Eigenschaften/Felder als Methode Ersatz für öffentliche Methoden. Für private Methoden ist es ein Werkzeug, aber nicht eine, die ich sehr oft verwende.
Instanz delegieren Felder mit einer pro-Instanz-Speicher Kosten. Wahrscheinlich ist eine vorzeitige Optimierung für die meisten Klassen, aber immer noch etwas im Auge zu behalten.
Ihrem code verwendet einen öffentlichen veränderliches Feld, das kann jederzeit geändert werden. Das tut weh Kapselung.
Wenn Sie die Feld-Initialisierer-syntax, können Sie keinen Zugang
this
. Also Feld-Initialisierer-syntax ist vor allem nützlich für statische Methoden.Macht eine statische Analyse sehr viel schwieriger, da die Umsetzung dieser Methode noch nicht bekannt ist, zur compile-Zeit.
Gibt es einige Fälle, in denen Delegierte Eigenschaften/Felder nützlich sein könnten:
Mit einer Schließung über lokale Variablen ist eine alternative zur Verwendung einer Methode und privaten Bereichen. Ich habe eine starke Abneigung gegen Klassen mit vielen Feldern, vor allem, wenn einige dieser Felder werden nur von zwei Methoden oder weniger. In diesen Situationen, mit Hilfe eines Delegaten in ein Feld werden kann, vorzuziehen, herkömmlichen Methoden
Diese Frage stellt eine falsche Dichotomie - zwischen-Funktionen und einer Stellvertretung mit einer entsprechenden Signatur. Der Hauptunterschied ist, dass einer der beiden sollte man nur benutzen, wenn es keine anderen Möglichkeiten. Verwenden Sie diese in Ihrer täglichen Arbeit, und es wird geworfen, aus der alle code-review.
Vorteile, die erwähnt wurden, sind weit aufgewogen durch die Tatsache, dass es fast nie einen Grund, um code zu schreiben, das ist so obskur, vor allem, wenn dieser code macht es Aussehen wie Sie nicht wissen, wie man programmiert in C#.
Ich fordere jeden Leser dieses ignorieren die Vorteile, die angegeben sind, denn Sie sind alle überwältigt von der Tatsache, dass dies ist die Art von code, der zeigt, dass Sie nicht wissen, wie ein Programm in C#.
Die einzige Ausnahme zu dieser Regel ist, wenn Sie eine Notwendigkeit, zum einen der nutzen, und dieses Bedürfnis kann nicht befriedigt werden, in irgendeiner anderen Weise. In diesem Fall müssen Sie schreiben, mehr Kommentar als code, um zu erklären, warum Sie haben einen guten Grund, es zu tun. Eine Antwort parat haben, so deutlich wie Eric Lippert hat. Du solltest besser in der Lage sein zu erklären, als auch Eric nicht, dass Sie nicht erreichen können, der Ihren Anforderungen und schreiben verständlich-code zur gleichen Zeit.