Adding and removing an anonymous event handler

I was wondering if this really works?

private void RegisterKeyChanged(T item) { item.OnKeyChanged += (o, k) => ChangeItemKey((T)o, k); } private void UnRegisterKeyChanged(T item) { item.OnKeyChanged -= (o, k) => ChangeItemKey((T)o, k); } 

How does the compiler know that the event handlers are the same? Is it even recommended?

+53
c # events anonymous-methods
Jan 12 '10 at 18:27
source share
7 answers

There is an MSDN page here that talks about this:

How to subscribe and unsubscribe to events

Please note in particular:

If you do not need to unsubscribe from the [sic] event later, you can use the assignment operator (+ =) to attach an anonymous method to the event.

As well as:

It is important to note that you cannot easily unsubscribe from an event if you used anonymous to subscribe to it. To unsubscribe in this scenario, it is necessary to return to the code where you are subscribing to the event, store the anonymous method in the delegate variable, and then add the delegate to the event. In general, we recommend that you do not use the anonymous event subscription function if you have to unsubscribe from an event at some later point in your code.

+59
Jan 12 '10 at 19:01
source share

For anyone interested, you can add and remove an anonymous event handler, for example:

 public class Musician { public void TuneGuitar() { Metronome metronome = new Metronome(); EventHandler<EventArgs> handler = null; handler = (sender, args) => { // Tune guitar // ... // Unsubscribe from tick event when guitar sound is perfect metronome.Tick -= handler; }; // Attach event handler metronome.Tick += handler; } } public class Metronome { event EventHandler<EventArgs> Tick; } 

UPDATE: In C # 7.0, we have support for local functions , so the TuneGuitar method TuneGuitar now be written as:

 public void TuneGuitar() { Metronome metronome = new Metronome(); void handler(object sender, EventArgs args) { // Tune guitar // ... // Unsubscribe from tick event when guitar sound is perfect metronome.Tick -= handler; }; // Attach event handler metronome.Tick += handler; } 
+12
Jun 10 '15 at 17:45
source share

If you need to unsubscribe from an event handler, you will need to have a specific link to a specific delegate. Looking at Delegate.Equality , you will find that delegates are not just compared using referential equality, however, it does not matter for anonymous delegates.

For an anonymous delegate, the compiler (basically) just creates a new “non-anonymous” delegate for each anonymous delegate, even if those who are the delegate are the same. Because of this, the structure will not find a delegate to unsubscribe when you use the code example you provided.

+6
Jan 12 '10 at 18:37
source share

This will not work, I'm afraid, because the two lambda expressions (and delegates) that you declared are actually different objects and return different links. Therefore, deleting a handler ( -= ) always fails.

A common solution to this problem (where you need to remove the handler) is to simply reorganize the lamba expression into the correct method. An alternative is to save the class variable for the event handler delegate and add and remove it, although I personally am not a fan of this. (This is more of a hassle than just creating a normal method, if anything.)

+3
Jan 12 '10 at 18:37
source share

I do not believe that this will work. If you really need to unregister from an event, you must specify an explicit event handler, which you can later unregister instead of an anonymous delegate.

+2
Jan 12 '10 at 18:32
source share

If you check with the document for Delegate.Equality, you will find out that they are not compared by reference.

+1
Jan 12 '10 at 18:31
source share

You can use this construct:

  private void button_Click(object sender, RoutedEventArgs e) { RoutedEventHandler onclick; // subcribe b_second.Click += onclick = (ss, aa) => { /* Just do what you need */ }; // unsubcribe b_second.Click -= onclick; } 
+1
Nov 16 '16 at 7:48
source share



All Articles