Ich sehe keine Vorteile der Verwendung von Ereignissen gegenüber Delegierten, außer syntaktischem Zucker. Vielleicht verstehe ich das falsch, aber es scheint, dass die Veranstaltung nur ein Platzhalter für Delegierte ist.
Würden Sie mir die Unterschiede erklären und wann welche zu verwenden sind? Was sind die Vor- und Nachteile? Unser Code ist stark mit Ereignissen verwurzelt, und ich möchte dem auf den Grund gehen.
Wann würden Sie Delegierte für Ereignisse einsetzen und umgekehrt? Bitte geben Sie Ihre reale Erfahrung mit beiden an, etwa im Produktionscode.
Antworten:
Aus technischer Sicht haben andere Antworten die Unterschiede angesprochen.
Aus semantischer Sicht sind Ereignisse Aktionen, die von einem Objekt ausgelöst werden, wenn bestimmte Bedingungen erfüllt sind. Zum Beispiel hat meine Aktienklasse eine Eigenschaft namens Limit und löst ein Ereignis aus, wenn die Aktienkurse das Limit erreichen. Diese Benachrichtigung erfolgt über ein Ereignis. Ob sich jemand wirklich um dieses Ereignis kümmert und es abonniert, ist für die Eigentümerklasse unerheblich.
Ein Delegat ist ein allgemeinerer Begriff, um ein Konstrukt zu beschreiben, das einem Zeiger in C / C ++ - Begriffen ähnelt. Alle Delegaten in .Net sind Multicast-Delegaten. Aus semantischer Sicht werden sie im Allgemeinen als eine Art Eingabe verwendet. Insbesondere sind sie eine perfekte Möglichkeit, das Strategiemuster umzusetzen . Wenn ich beispielsweise eine Liste von Objekten sortieren möchte, kann ich der Methode eine Komparatorstrategie bereitstellen, um der Implementierung mitzuteilen, wie zwei Objekte verglichen werden sollen.
Ich habe die beiden Methoden im Produktionscode verwendet. Tonnen meiner Datenobjekte benachrichtigen, wenn bestimmte Eigenschaften erfüllt sind. Das einfachste Beispiel: Wenn sich eine Eigenschaft ändert, wird ein PropertyChanged-Ereignis ausgelöst (siehe INotifyPropertyChanged-Schnittstelle). Ich habe Delegaten im Code verwendet, um verschiedene Strategien zum Verwandeln bestimmter Objekte in Zeichenfolgen bereitzustellen. Dieses spezielle Beispiel war eine verherrlichte ToString () - Liste von Implementierungen für einen bestimmten Objekttyp, um sie den Benutzern anzuzeigen.
quelle
Das Schlüsselwort
event
ist ein Bereichsmodifikator für Multicast-Delegaten. Die praktischen Unterschiede zwischen diesem und der bloßen Erklärung eines Multicast-Delegierten sind folgende:event
in einer Schnittstelle verwenden.public event
. B. ) festgelegt.Interessanterweise können Sie Multicast-Delegaten anwenden
+
und anwenden.-
Dies ist die Grundlage für die Syntax+=
und die-=
Syntax für die kombinierte Zuweisung von Delegaten zu Ereignissen. Diese drei Schnipsel sind äquivalent:Beispiel zwei, das sowohl die direkte Zuordnung als auch die Kombinationszuordnung veranschaulicht.
Beispiel drei: bekanntere Syntax. Sie kennen wahrscheinlich die Zuweisung von null, um alle Handler zu entfernen.
Ereignisse haben wie Eigenschaften eine vollständige Syntax, die niemand jemals verwendet. Dies:
... macht genau das Gleiche wie folgt :
Die Methoden zum Hinzufügen und Entfernen sind in der von VB.NET verwendeten eher gestelzenen Syntax auffälliger (keine Operatorüberladungen).
quelle
Ereignisse sind syntaktischer Zucker. Sie sind lecker. Wenn ich eine Veranstaltung sehe, weiß ich, was zu tun ist. Wenn ich einen Delegierten sehe, bin ich mir nicht so sicher.
Das Kombinieren von Ereignissen mit Schnittstellen (mehr Zucker) ergibt einen köstlichen Snack. Delegierte und reine virtuelle abstrakte Klassen sind viel weniger appetitlich.
quelle
Ereignisse sind in den Metadaten als solche gekennzeichnet. Auf diese Weise können Windows Forms- oder ASP.NET-Designer Ereignisse von bloßen Eigenschaften des Delegattyps unterscheiden und diese entsprechend unterstützen (insbesondere auf der Registerkarte Ereignisse des Eigenschaftenfensters anzeigen).
Ein weiterer Unterschied zu einer Eigenschaft vom Delegatentyp besteht darin, dass Benutzer nur Ereignishandler hinzufügen und entfernen können, während sie mit einer Eigenschaft vom Delegattyp den Wert festlegen können:
Dies hilft, Ereignisabonnenten zu isolieren: Ich kann meinen Handler einem Ereignis hinzufügen, und Sie können Ihren Handler demselben Ereignis hinzufügen, und Sie werden meinen Handler nicht versehentlich überschreiben.
quelle
Obwohl Ereignisse normalerweise mit Multicast-Delegaten implementiert werden, ist es nicht erforderlich, dass sie auf diese Weise verwendet werden. Wenn eine Klasse ein Ereignis verfügbar macht, bedeutet dies, dass die Klasse zwei Methoden verfügbar macht. Ihre Bedeutungen sind im Wesentlichen:
Die häufigste Methode für eine Klasse, ein offengelegtes Ereignis zu behandeln, besteht darin, einen Multicast-Delegaten zu definieren und alle Delegaten hinzuzufügen / zu entfernen, die an die oben genannten Methoden übergeben werden. Es ist jedoch nicht erforderlich, dass sie auf diese Weise funktionieren. Leider kann die Ereignisarchitektur einige Dinge nicht tun, die alternative Ansätze viel sauberer gemacht hätten (z. B. hätte die Abonnementmethode einen MethodInvoker zurückgegeben, der vom Abonnenten beibehalten würde; um ein Ereignis abzumelden, rufen Sie einfach die zurückgegebene Methode auf), so dass Multicast-Delegierte sind bei weitem der häufigste Ansatz.
quelle
Um die Unterschiede zu verstehen, können Sie sich diese beiden Beispiele ansehen
Beispiel mit Delegierten (Aktion in diesem Fall, bei der es sich um eine Art Delegat handelt, der keinen Wert zurückgibt)
Um den Delegaten zu verwenden, sollten Sie so etwas tun
Dieser Code funktioniert gut, aber Sie könnten einige Schwachstellen haben.
Zum Beispiel, wenn ich das schreibe
Mit der letzten Codezeile hatte ich die vorherigen Verhaltensweisen überschrieben, nur mit einer fehlenden
+
(ich habe+
statt verwendet+=
)Eine weitere Schwachstelle ist, dass jede Klasse, die Ihre
Animal
Klasse verwendet,RaiseEvent
nur einen Aufruf auslösen kannanimal.RaiseEvent()
.Um diese Schwachstellen zu vermeiden, können Sie
events
in c # verwenden.Ihre Tierklasse wird sich auf diese Weise ändern
Ereignisse aufrufen
Unterschiede:
Anmerkungen
EventHandler wird als folgender Delegat deklariert:
Es werden ein Absender (vom Objekttyp) und Ereignisargumente benötigt. Der Absender ist null, wenn er aus statischen Methoden stammt.
Sie können
EventHAndler
stattdessen auch dieses Beispiel verwendenEventHandler<ArgsSpecial>
siehe hier für die Dokumentation über Eventhandler
quelle
Wenn ich meine eigenen APIs entwerfe, definiere ich Delegaten, die als Parameter an Methoden oder an die Konstruktoren von Klassen übergeben werden:
Predicate
und dieAction
Delegaten an die generischen .Net-Auflistungsklassen übergeben).Diese Delegaten sind zur Laufzeit im Allgemeinen nicht optional (dh müssen es nicht sein
null
).Ich neige dazu, keine Ereignisse zu verwenden. aber wo ich Gebrauch Ereignisse tun, ich benutze sie für optional Ereignisse signalisiert Null, eine oder mehrere Clients , die könnten interessiert sein, das heißt , wenn es Sinn macht , dass eine Klasse (zB
System.Windows.Form
Klasse) sollte vorhanden sein und laufen , ob irgendein Kunde hat hat seinem Ereignis einen Ereignishandler hinzugefügt (z. B. ist das Ereignis "Maus nach unten" des Formulars vorhanden, es ist jedoch optional, ob ein externer Client daran interessiert ist, einen Ereignishandler für dieses Ereignis zu installieren).quelle
Obwohl ich keine technischen Gründe dafür habe, verwende ich Ereignisse im Code im UI-Stil, dh in den höheren Codeebenen, und verwende Delegaten für Logik, die tiefer im Code liegt. Wie ich bereits sagte, könnten Sie beides verwenden, aber ich finde, dass dieses Verwendungsmuster logisch einwandfrei ist. Wenn nichts anderes, hilft es, die Arten von Rückrufen und ihre Hierarchie zu dokumentieren.
Bearbeiten: Ich denke, der Unterschied in meinen Nutzungsmustern besteht darin, dass ich es durchaus akzeptabel finde, Ereignisse zu ignorieren. Es handelt sich um Hooks / Stubs. Wenn Sie über das Ereignis Bescheid wissen müssen, hören Sie sie sich an, wenn Sie sich nicht darum kümmern Das Ereignis ignoriert es einfach. Deshalb benutze ich sie für die Benutzeroberfläche, eine Art Javascript / Browser-Ereignisstil. Wenn ich jedoch einen Delegierten habe, erwarte ich WIRKLICH, dass jemand die Aufgabe des Delegierten übernimmt und eine Ausnahme auslöst, wenn sie nicht behandelt wird.
quelle
Der Unterschied zwischen Veranstaltungen und Delegierten ist viel geringer als ich dachte. Ich habe gerade ein superkurzes YouTube-Video zu diesem Thema gepostet: https://www.youtube.com/watch?v=el-kKK-7SBU
Hoffe das hilft!
quelle
quelle