Ist es möglich, eine anonyme Methode von einem Ereignis abzumelden?
Wenn ich eine Veranstaltung wie diese abonniere:
void MyMethod()
{
Console.WriteLine("I did it!");
}
MyEvent += MyMethod;
Ich kann mich wie folgt abmelden:
MyEvent -= MyMethod;
Aber wenn ich mich mit einer anonymen Methode anmelde:
MyEvent += delegate(){Console.WriteLine("I did it!");};
Ist es möglich, diese anonyme Methode abzubestellen? Wenn das so ist, wie?
Antworten:
Behalten Sie einfach einen Verweis auf den Delegierten in der Nähe.
quelle
Eine Technik besteht darin, eine Variable zu deklarieren, die die anonyme Methode enthält, die dann in der anonymen Methode selbst verfügbar wäre. Dies funktionierte für mich, da das gewünschte Verhalten darin bestand, sich abzumelden, nachdem das Ereignis behandelt wurde.
Beispiel:
quelle
Aus dem Speicher garantiert die Spezifikation das Verhalten in Bezug auf die Äquivalenz von Delegaten, die mit anonymen Methoden erstellt wurden, in keiner Weise.
Wenn Sie sich abmelden müssen, sollten Sie entweder eine "normale" Methode verwenden oder den Delegaten an einer anderen Stelle behalten, damit Sie sich mit genau demselben Delegaten abmelden können, den Sie zum Abonnieren verwendet haben.
quelle
In 3.0 kann verkürzt werden auf:
quelle
Da die Funktion für lokale Funktionen von C # 7.0 veröffentlicht wurde, wird der von J c vorgeschlagene Ansatz wirklich ordentlich.
Ehrlich gesagt haben Sie hier keine anonyme Funktion als Variable. Aber ich nehme an, die Motivation, es in Ihrem Fall zu verwenden, kann auf lokale Funktionen angewendet werden.
quelle
Anstatt einen Verweis auf einen Delegierten zu behalten, können Sie Ihre Klasse instrumentieren, um die Aufrufliste des Ereignisses an den Anrufer zurückzugeben. Grundsätzlich können Sie so etwas schreiben (vorausgesetzt, MyEvent ist in MyClass deklariert):
So können Sie von außerhalb von MyClass auf die gesamte Aufrufliste zugreifen und jeden gewünschten Handler abbestellen. Zum Beispiel:
Ich habe einen vollständigen Beitrag über dieses tecnique geschrieben hier .
quelle
Art von lahmem Ansatz:
Dies funktioniert möglicherweise nicht oder ist die effizienteste Methode, sollte aber die Arbeit erledigen.
quelle
Wenn Sie die Abmeldung kontrollieren möchten, müssen Sie den in Ihrer akzeptierten Antwort angegebenen Weg gehen. Wenn Sie jedoch nur Bedenken haben, Referenzen zu löschen, wenn Ihre abonnierende Klasse den Gültigkeitsbereich verlässt, gibt es eine andere (leicht verschlungene) Lösung, bei der schwache Referenzen verwendet werden. Ich habe gerade eine Frage und Antwort zu diesem Thema gepostet .
quelle
Eine einfache Lösung:
Übergeben Sie einfach die eventhandle-Variable als Parameter an sich selbst. Wenn Sie den Fall haben, dass Sie aufgrund von Multithreading nicht auf die ursprünglich erstellte Variable zugreifen können, können Sie Folgendes verwenden:
quelle
MyEvent -= myEventHandlerInstance;
wird? Wenn es möglich ist, haben Sie einen Fehler. Aber ich bin mir nicht sicher, ob das der Fall ist.Wenn Sie mit diesem Delegaten auf ein Objekt verweisen möchten, können Sie möglicherweise Delegate.CreateDelegate (Typ, Objektziel, MethodInfo methodInfo) .net verwenden
quelle
Wenn der beste Weg darin besteht, eine Referenz auf dem abonnierten eventHandler zu behalten, kann dies mithilfe eines Wörterbuchs erreicht werden.
In diesem Beispiel muss ich eine anonyme Methode verwenden, um den Parameter mergeColumn für eine Reihe von DataGridViews einzuschließen.
Die Verwendung der MergeColumn-Methode mit dem auf true gesetzten Parameter enable aktiviert das Ereignis, während die Verwendung mit false es deaktiviert.
quelle