2009-04-30 3 views
26

Ich habe den folgenden Code, um die GUI auf eine Änderung in der Sammlung reagieren zu lassen.Wie kann ich mich von einem Event abmelden, das einen Lambda-Ausdruck verwendet?

myObservableCollection.CollectionChanged += ((sender, e) => UpdateMyUI()); 

Vor allem ist dies ein guter Weg, dies zu tun?

Zweitens: Was ist der Code zum Abbestellen von diesem Ereignis? Ist es gleich aber mit - = (und dann nochmal die komplette anonyme Methode)?

+0

? Duplizieren: http://stackoverflow.com/questions/183367/unsubscribe-anonymous-method-in-c – Richard

+0

Siehe [this] (http://stackoverflow.com/questions/183367/unsubscribe-anonym-method -in-c). –

+0

Ich habe meinen Lambda-Ausdruck nicht in einen Delegaten eingefügt (wie in Ihrem Link), daher habe ich keinen Hinweis auf die Abmeldung. –

Antwort

20

Wenn Sie sich von einer Veranstaltung abmelden müssen, benötigen Sie eine instanzierte Referenz. Leider bedeutet das, dass Sie diese spezielle Syntax nicht verwenden können.

+2

Wenn Sie unter "dieser speziellen Syntax" das Erzeugen des Lambda und das Hinzufügen des Handlers in einer Zeile verstehen, dann ja. Die einfache Lösung ist nur eine Referenz auf das Lambda zu speichern. Wirklich, ich denke, dass das OP mit einer gewöhnlichen Methode arbeiten sollte, wenn er es wiederholt referenzieren muss - es verbessert die Lesbarkeit, zumindest in meinen Gedanken. – Noldorin

+0

Danke für die Klärung. –

+0

@Noldorin Ja, das meinte ich mit "dieser speziellen Syntax". Und ich stimme dir vollkommen zu. –

35

Vor allem ... ja es ist ein guter Weg, es zu tun, es ist sauber, kleine Form und leicht zu lesen & verstehen ... der Vorbehalt ist natürlich "Es sei denn, Sie später abbestellen".

Ich glaube, Jon Skeet wies darauf hin, dass "die Spezifikation explizit nicht das Verhalten in beide Richtungen garantiert, wenn es um Äquivalenz von Delegaten mit anonymen Methoden erstellt wird."

Wenn Sie sich zu einem späteren Zeitpunkt vom Ereignis abmelden müssen, sollten Sie am besten eine Delegat-Instanz erstellen, damit Sie sich später an die Referenz halten können.

var myDelegate = delegate(sender, e){UpdateMyUI()}; 

myObservableCollection.CollectionChanged += myDelegate; 

myObservableCollection.CollectionChanged -= myDelegate; 
+0

var myDelegate = Delegat (Absender, e) {UpdateMyUI()}; Kompiliert nicht ... Sie müssen den Delegattyp angeben. John Skeet verwendet in seinem Beispiel den Action-Delegaten, der jedoch nur ein Argument benötigt. Welchen Delegattyp sollten wir in Ihrem Beispiel verwenden? –

+1

@RaduSimionescu: Das gleiche wie der Typ des Ereignisses, das in diesem Beispiel 'NotifyCollectionChangedEventHandler' wäre –

1

Es ist ein oker Weg zu gehen, es sei denn, myObservableCollection länger leben wird als ‚this‘, wobei in diesem Fall könnten Sie mit einem Speicherverlust, als Delegierter am Ende, die hinter den Kulissen erstellt wird, wird ein konservieren Hinweis auf Ihr 'Dies', das es am Leben erhalten wird. Wenn Sie das Ereignis, das gerade zu hören ist, wiederholt erstellen und "zerstören", werden Sie feststellen, dass sie nicht vom Garbage Collector erfasst werden.

Wenn dies ein Problem ist, können Sie die in den Antworten vorgeschlagene Route verwenden und dabei einen Verweis auf den Handler beibehalten, den Sie zuerst erstellen müssen.

Eine andere Lösung besteht darin, schwache Referenzen zu verwenden, um einen Event-Handler zu erstellen, mit dem der Abonnent erfasst werden kann, wenn keine anderen Referenzen vorhanden sind. Ich habe diese Lösung in this question and answer erforscht.