Ich habe einige Erwähnungen dieser Redewendung gesehen (auch auf SO ):
// Deliberately empty subscriber
public event EventHandler AskQuestion = delegate {};
Der Vorteil ist klar - es wird vermieden, dass vor dem Auslösen des Ereignisses nach Null gesucht werden muss.
Ich bin jedoch sehr gespannt, ob es Nachteile gibt. Ist es beispielsweise weit verbreitet und transparent genug, um keine Wartungsprobleme zu verursachen? Gibt es einen nennenswerten Leistungseinbruch beim leeren Teilnehmeranruf?
Verwenden Sie eine Erweiterungsmethode , um beide Probleme zu lösen, anstatt Leistungsaufwand zu verursachen:
Einmal definiert, müssen Sie nie wieder eine Null-Ereignisprüfung durchführen:
quelle
handler
obige Parameter ist ein Wertparameter für die Methode. Es wird sich nicht ändern, während die Methode ausgeführt wird. Dazu müsste es sich um einenref
Parameter handeln (offensichtlich darf ein Parameter nicht sowohl denref
als auch denthis
Modifikator enthalten) oder natürlich um ein Feld.Bei Systemen, die Ereignisse stark nutzen und leistungskritisch sind , sollten Sie dies zumindest in Betracht ziehen nicht . Die Kosten für das Auslösen eines Ereignisses mit einem leeren Delegierten sind ungefähr doppelt so hoch wie die Kosten für das Auslösen mit einem Null-Check.
Hier sind einige Zahlen, die Benchmarks auf meinem Computer ausführen:
Und hier ist der Code, mit dem ich diese Zahlen erhalten habe:
quelle
Wenn Sie es mit / lot / tun, möchten Sie möglicherweise einen einzelnen statischen / gemeinsam genutzten leeren Delegaten haben, den Sie wiederverwenden, um einfach das Volumen der Delegateninstanzen zu verringern. Beachten Sie, dass der Compiler diesen Delegaten ohnehin pro Ereignis (in einem statischen Feld) zwischenspeichert, sodass es sich nur um eine Delegateninstanz pro Ereignisdefinition handelt. Dies ist also keine große Einsparung - aber möglicherweise sinnvoll.
Das Feld pro Instanz in jeder Klasse nimmt natürlich immer noch den gleichen Platz ein.
dh
Davon abgesehen scheint es in Ordnung zu sein.
quelle
Es gibt keine sinnvollen Leistungseinbußen, über die man sprechen könnte, außer möglicherweise für einige extreme Situationen.
Beachten Sie jedoch, dass dieser Trick in C # 6.0 weniger relevant wird, da die Sprache eine alternative Syntax zum Aufrufen von Delegaten bietet, die möglicherweise null ist:
Oben
?.
kombiniert der bedingte Nulloperator die Nullprüfung mit einem bedingten Aufruf.quelle
Nach meinem Verständnis ist der leere Delegat threadsicher, die Nullprüfung dagegen nicht.
quelle
Ich würde sagen, es ist ein gefährliches Konstrukt, weil es Sie dazu verleitet, etwas zu tun wie:
Wenn der Client eine Ausnahme auslöst, geht der Server mit.
Vielleicht tun Sie es also:
Was passiert jedoch mit den anderen Abonnenten, wenn Sie mehrere Abonnenten haben und ein Abonnent eine Ausnahme auslöst?
Zu diesem Zweck habe ich einige statische Hilfsmethoden verwendet, die die Nullprüfung durchführen und jede Ausnahme von der Abonnentenseite verschlucken (dies ist von idesign).
quelle
Try.TryAction()
Funktion, nicht mit einem explizitentry{}
Block), aber ich ignoriere die Ausnahmen nicht, ich melde sie ...Anstelle des Ansatzes "leerer Delegat" kann eine einfache Erweiterungsmethode definiert werden, um die herkömmliche Methode zum Überprüfen des Ereignishandlers gegen Null zu kapseln. Es wird hier und hier beschrieben .
quelle
Als Antwort auf diese Frage fehlt bisher eines: Es ist gefährlich, die Prüfung auf den Nullwert zu vermeiden .
Die Sache ist: Sie wissen nie, wer Ihren Code auf welche Weise verwenden wird. Sie wissen nie, ob in einigen Jahren während einer Fehlerbehebung Ihres Codes das Ereignis / der Handler auf null gesetzt ist.
Schreiben Sie immer den if-Check.
Hoffentlich hilft das ;)
ps: Danke für die Leistungsberechnung.
pps: Bearbeitet von einem Ereignisfall zu einem Rückrufbeispiel. Vielen Dank für das Feedback ... Ich habe das Beispiel ohne Visual Studio "codiert" und das Beispiel, das ich mir vorgestellt hatte, an ein Ereignis angepasst. Entschuldigung für die Verwirrung.
ppps: Weiß nicht, ob es noch zum Thread passt ... aber ich denke, es ist ein wichtiges Prinzip. Bitte überprüfen Sie auch einen anderen Thread von Stackflow
quelle
protected
. Sie können das Ereignis nur von der Klasse selbst (oder von einer abgeleiteten Klasse) trennen.