Nehmen Sie an der folgenden C # -Klasse teil:
c1 {
event EventHandler someEvent;
}
Wenn es viele Abonnements für c1
die someEvent
Veranstaltung gibt und ich sie alle löschen möchte, wie kann ich dies am besten erreichen? Bedenken Sie auch, dass Abonnements für diese Veranstaltung Lambdas / anonyme Delegierte sein können / sind.
Derzeit besteht meine Lösung darin, eine ResetSubscriptions()
Methode hinzuzufügen c1
, die someEvent
auf null gesetzt ist. Ich weiß nicht, ob dies unsichtbare Konsequenzen hat.
EventHandlerList
, können Sie dies möglicherweise. Sie müssten diese beiden Fälle jedoch erkennen - und es könnte eine beliebige Anzahl anderer Implementierungen geben.hidden
.Fügen Sie c1 eine Methode hinzu, die 'someEvent' auf null setzt.
quelle
Es ist besser zu verwenden,
delegate { }
alsnull
die Null-Ref-Ausnahme zu vermeiden.quelle
List.Clear()
vsmyList = null
.Das Setzen des Ereignisses auf null innerhalb der Klasse funktioniert. Wenn Sie eine Klasse entsorgen, sollten Sie das Ereignis immer auf null setzen. Der GC hat Probleme mit Ereignissen und bereinigt die entsorgte Klasse möglicherweise nicht, wenn baumelnde Ereignisse vorliegen.
quelle
Die beste Vorgehensweise zum Löschen aller Abonnenten besteht darin, someEvent durch Hinzufügen einer weiteren öffentlichen Methode auf null zu setzen, wenn Sie diese Funktionalität für externe Benutzer verfügbar machen möchten. Dies hat keine unsichtbaren Konsequenzen. Voraussetzung ist, dass Sie SomeEvent mit dem Schlüsselwort 'event' deklarieren.
Bitte lesen Sie das Buch - C # 4.0 auf den Punkt gebracht, Seite 125.
Jemand hier schlug vor,
Delegate.RemoveAll
Methode zu verwenden . Wenn Sie es verwenden, kann der Beispielcode dem folgenden Formular folgen. Aber es ist wirklich dumm. Warum nicht einfachSomeEvent=null
innerhalb derClearSubscribers()
Funktion?quelle
Sie können dies mithilfe der Methoden Delegate.Remove oder Delegate.RemoveAll erreichen.
quelle
Konzeptionell erweiterter langweiliger Kommentar.
Ich verwende lieber das Wort "Ereignishandler" anstelle von "Ereignis" oder "Delegieren". Und benutzte das Wort "Ereignis" für andere Sachen. In einigen Programmiersprachen (VB.NET, Object Pascal, Objective-C) wird "Ereignis" als "Nachricht" oder "Signal" bezeichnet und verfügt sogar über ein Schlüsselwort "Nachricht" und eine bestimmte Zuckersyntax.
Um auf diese "Nachricht" zu antworten, antwortet ein "Ereignishandler", unabhängig davon, ob es sich um einen einzelnen oder mehrere Delegierte handelt.
Zusammenfassung: "Ereignis" ist die "Frage", "Ereignishandler" sind die Antwort (en).
quelle
Das ist meine Lösung:
Sie müssen Muster aufrufen
Dispose()
oder verwendenusing(new Foo()){/*...*/}
, um alle Mitglieder der Aufrufliste abzumelden.quelle
Entfernen Sie alle Ereignisse. Nehmen Sie an, dass das Ereignis vom Typ "Aktion" ist:
quelle
GetInvocationList
.Anstatt Rückrufe manuell hinzuzufügen und zu entfernen und eine Reihe von Delegatentypen überall deklarieren zu lassen:
Sie könnten diesen generischen Ansatz ausprobieren:
quelle