Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Anonymous event handlers and disposing

Tags:

c#

disposing

I have a rather short question about anonymous event handlers:

This is the code that I have:

public void AddTestControl(Control ctrl)
{
    ctrl.Disposed += (o, e) => { RemoveTestControl(ctrl); };
    ctrl.SomeEvent += _Control_SomeEvent;
}

public void RemoveTestControl(Control ctrl)
{
    ctrl.SomeEvent -= _Control_SomeEvent;
}

Is this code above fine, or should the code be rewritten in order to remove the Disposed Event Handler? Something like this:

public void AddTestControl(Control ctrl)
{
    ctrl.Disposed += _Control_Disposed;
    ctrl.SomeEvent += _Control_SomeEvent;
}

public void RemoveTestControl(Control ctrl)
{
    ctrl.Disposed -= _Control_Disposed;
    ctrl.SomeEvent -= _Control_SomeEvent;
}
like image 826
juFo Avatar asked Mar 02 '12 09:03

juFo


People also ask

Can you unsubscribe an anonymous method in C#?

You cannot easily unsubscribe from an event if you used an anonymous function to subscribe to it.

What are event handlers used for?

Event handlers can be used to handle and verify user input, user actions, and browser actions: Things that should be done every time a page loads. Things that should be done when the page is closed. Action that should be performed when a user clicks a button.

Can events be static C#?

An event may be declared as a static event by using the static keyword. This makes the event available to callers at any time, even if no instance of the class exists. For more information, see Static Classes and Static Class Members. An event can be marked as a virtual event by using the virtual keyword.


2 Answers

Generally, the only situation where you need to remove the event handlers from an object in order for it to be eligible for garbage collection is when the publisher object (the one defining the event) lives longer than the subscriber object (the one containing the event handlers). In such a situation the GC won't be able to release the subscriber when it goes out of scope since it's still being referenced by the publisher.

In this case, assuming this is WebForms or WinForms, the publisher (that is the Control object), is most likely a child object of the subscriber (probably a Page or a Form), which will be the first to go out of scope taking all its associated objects with it. Hence there's no need to remove the event handlers.

like image 96
Enrico Campidoglio Avatar answered Oct 26 '22 19:10

Enrico Campidoglio


It always feels cleaner to me to unsubscribe from events, even in situations where I know the subscribers always outlive the publisher (the object raising the event): the event will never be raised again, the publisher is no longer reachable and can be collected.

Then again, how many people go to the trouble of unsubscribing every event handler in e.g. a WinForms application? The object references point from the publisher to the subscribers, not the other way around, so the publisher can be collected while the subscribers live on. It doesn't present the same danger as the opposite situation, where a long-lived publisher (e.g. a static event) can wastefully keep potentially large subscribers alive long after they could have been collected.

If you want/need to unsubscribe, then the requirement to unsubscribe the same delegate makes anonymous event handlers a bit of a pain. The Reactive Extensions solve this problem in a neat way: rather than having to remember the delegate you subscribed, subscribing returns an IDisposable which unsubscribes when disposed. Chucking all your subscriptions into a CompositeDisposable lets you unsubscribe everything with just one Dispose call.

like image 29
anton.burger Avatar answered Oct 26 '22 19:10

anton.burger