Sollte der Absender eines Ereignisses immer ein generisches Objekt sein?


10

Beim Programmieren von Ereignissen in C # wird empfohlen , einen Delegaten in folgender Form zu erstellen:

delegate XEventHandler(object sender, XEventArgs e);

Meine Frage bezieht sich auf das erste Argument des Delegierten object sender. Muss es immer ein Generikum sein object? Ein Absender vom Typ führt objectimmer zu einem ähnlichen Code.

val = ((ConcreteType)sender).Property;

oder noch ausführlicher,

ConcreteType obj = sender as ConcreteType
if (obj != null) { ... }

Ein Argument gegen stark typisierte Absender ist, dass andere Objekte das Ereignis weiterleiten können , ohne sich um den Typ zu kümmern. Während dies in GUI-Umgebungen sinnvoll sein kann, bin ich mir nicht sicher, ob es außerhalb einer GUI von Nutzen sein könnte.

Was ist, wenn die Klasse des Absenders immer bekannt ist (zumindest als abstrakte Klasse)? Zum Beispiel, wenn ich eine bin die Umsetzung ListChangedEreignisses in einer abstrakten ListKlasse, und wenn andere Klassen werden es (zB erben LinkedList, ArrayList), ist es in Ordnung , meinen Delegaten mit einem Sender des Typs zu definieren List?

delegate ListChangedEventHander(List sender, ListChangedEventArgs e);

Oder hätte es einen Nachteil, den konventionellen object senderauf einen spezifischeren Typ umzustellen?

Antworten:


10

Zu diesem Zeitpunkt ist es meistens eine (ziemlich starke) Konvention. Das heißt, es ist seltsam, wenn Sie eine Bibliothek schreiben, die dieser Konvention nicht entspricht.

In den Event Design Guidelines heißt es:

DO Verwendung objectals Typ des ersten Parameters der Event - Handler, und es nennt sender.

Möglicherweise stellen Sie jedoch fest, dass die aktuelle Anleitung besagt, dass Sie keinen eigenen benutzerdefinierten Delegaten für Ereignisse definieren, sondern EventHandler<T>stattdessen verwenden sollten, wenn Sie können.

Was das Design betrifft, würde ich vermuten, dass es auch die Wiederverwendung von Event-Handlern fördert, selbst in Kontexten, die ursprünglich nicht vom ursprünglichen Designer des Events vorgesehen waren.


2
Ughhh ... nur weil Microsoft beschlossen hat, seine Richtlinien so allgemein zu gestalten, dass sie für alle gelten, heißt das nicht, dass es für alle anderen eine gute Idee ist, ihre Richtlinien zu befolgen. Es ist sehr wahrscheinlich, dass "alle anderen" keinen Code schreiben, der von Millionen anderer Entwickler verwendet werden soll. Ich habe mich bei ungefähr 2/3 der Empfehlungen des von Ihnen angegebenen Links zusammengekauert.
Dunk

Um ehrlich zu sein, fühlt sich diese "Richtlinie" mehr oder weniger wie die ungarische Notation der Windows-API an. Jemand, der brillant war, hat es aus einem wirklich guten Grund angefangen und dann haben alle anderen angefangen, es zu missbrauchen. Wenn es eine Richtlinie gibt, gibt es besser einen guten Grund für diese Richtlinie. Und was ich denke , der Grund für diese Richtlinie ist , dass System.Windows.FormsNamespace ist der Ort, wo Ereignisse am häufigsten besucht werden, und es sinnvoll , auf denen abonnieren ClickFall Buttonoder ein CheckBox. Damit der Absender muss generisch sein. ...
Sampathsris

... Aber wenn es um andere, spezifischere, enthaltene Funktionsbereiche geht, muss der Absender möglicherweise keine generische Klasse sein. Siehe noch einmal mein Beispiel einer Klassenhierarchie von Lists.
Sampathsris

11
@ Dunk: Und das ist der Punkt. Diese Richtlinie stammt aus den Framework Design Guidelines, die sich hauptsächlich mit Code befassen , der von anderen verwendet wird . Nicht weil es die beste Lösung ist, sondern weil es am wenigsten überraschend ist. Das ist die beste Option für ein Framework . Wenn der Anwendungsfall für kleinere Bibliotheken genau angegeben ist, gelten weniger Anleitungen. Microsoft sagt dies ausdrücklich am Anfang des Buches.
Magus

1
Ich streite nicht mit der Antwort, ich habe sie sogar positiv bewertet, weil sie aus einer seriösen Quelle stammt. Ich sage nur, dass ich die Richtlinien nicht verwenden würde. Wenn ein Ereignis bestimmte Daten senden soll, sende ich nur die spezifischen Daten. Außerdem funktioniert die Ereignisfunktion einwandfrei, wenn Sie sie so verwenden, wie sie verwendet werden sollen.
Dunk

0

Der Grund für die Empfehlung ist, dass zukünftige Änderungen möglich sind, die nicht unbedingt Änderungen am vorhandenen Code und insbesondere an der öffentlichen Schnittstelle erfordern.

Der Ereignismechanismus selbst kann weiterhin für Ereignisse im "VB6" -Stil verwendet werden. Sie müssen jedoch alle vorhandenen Konsumenten ändern, wenn Sie jemals die Signatur ändern müssen (oder schlimmer noch: Erstellen Sie neue Versionen derselben Ereignisse). Mit dem empfohlenen Ansatz können Sie die Signatur aktualisieren, ohne den vorhandenen Code zu reparieren, solange die neueren Elemente von den vorhandenen erben.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.