Do you need to “unwire” an anonymous function/lamb

2019-04-06 11:22发布

问题:

My understanding is that any event handlers wired up in C# need to be unwired as such.

Object myObject = new Object();
myObject.Event += EventHandler; //Wired
myObject.Event -= EventHandler; //Unwired

But do you need to unwire the following code? and if so, how?

Object myObject = new Object();
myObject.Event += (object sender, EventArgs e) => { }; //Wired
myObject.Event -= ????? //Unwire? How?

My assumption is no?

回答1:

Yes, you need to (*) and you need to do it like this:

Object myObject = new Object();
EventHandler handler = (object sender, EventArgs e) => { };
myObject.Event += handler; //Wired
myObject.Event -= handler; //Unwired

See here for an explanation.

(*)
You don't need to do it because of garbage collection. You need to do it, if you don't want the event to call your handler any more.

UPDATE:
To clarify a bit:
The only reason, why you want to unwire an event handler is that the object defining the event handler can be garbage collected.
Think about the following example:

  • You have a class PowerSource with an event BlackOut.
  • You have a class LightBulb that will be on, as long as there is power. It has a method ConnectToPowerSource. This method subscribes to the BlackOut event of the supplied PowerSource.
  • You have a collection that contains the light bulbs

Now, simply removing a light bulb from the list will not make it get garbage collected, because the PowerSource is still holding a reference to the LightBulb instance in its BlackOut event. Only after unregistering the LightBulb from the BlackOut event will make the LightBulb get garbage collected.



回答2:

Yes, you do have to. Because an event is a strong reference, your event handler will continue to be invoked.

You can remove it as follows:

EventHandler handler = (s,e) => { DoSomething(); }
myObject.Event += handler; 
myObject.Event -= handler; 


回答3:

Object myObject = new Object();
EventHandler h = (object sender, EventArgs e) => { }; //Wired
myObject.Event += h;
myObject.Event -= h;

Or, to unwire in the handler:

Object myObject = new Object();
EventHandler h = null; //need to declare h to use it in the following line
//compiler/resharper will complain about modified closure
h = (object sender, EventArgs e) => { myObject.Event-=h; };
myObject.Event += h;