Should all Objects that register events be IDisposable

95 views Asked by At

As per my understanding when an Object is no longer required it is best practice to unsubscribe all event handlers in any Objects that subscribes to events.

This is done to avoid handling an event within an Object when the given Object may reside in a invalid state (no doubt among other reasons that I'm probably unaware of).

Given the above, I have found myself implementing IDisposible on all my Objects that register any form of event handlers. However, this creates the obvious complexity of having to explicitly call Dispose() on the given object.

In the end, I find myself uncertain if this extra complexity is required or if I should simply perform the event unsubscription in the object destructor. However this obviously leaves open the possibility of unexpected behavior given that Object destruction is non-deterministic.

So should all Objects that register for events be IDisposable? Or is there an alternative approach that is better suited?

2

There are 2 answers

0
supercat On BEST ANSWER

I would suggest that if an object subscribes to notifications from outside objects, whether those objects use events, IObservable, or other means of subscription, disposing the object should ensure that those subscriptions get canceled; the most natural way to do that is for it to use the normal means of cancellation supported by those outside objects.

I would further suggest that if an object accepts subscription requests from outside objects, it should destroy references to those objects if/when it becomes apparent that no notifications will ever again be sent to those subscribers. Generally, once an object has sent any notifications that would be required by Dispose itself, it won't have to send any further notifications and should thus destroy its subscription lists unless its semantics require them to be kept beyond that.

While the .NET event pattern does not make it convenient to ensure that subscriptions get cancelled, failure to cancel subscriptions from shared objects will often result in code which will "usually" work, but will have some hard-to-validate requirements. In cases where a few objects are created and kept, or an unbounded number are created and all are abandoned, mutual references among the objects won't cause memory leaks since in the former case the objects would need to be retained even if the mutual references didn't exist, and in the latter case they would cease to exist despite the mutual references. Cases where an unbounded number of objects are created and all but a few are abandoned, however, can be disastrous. Even if many objects' consumers will naturally abide by one or the other usage pattern, requiring that all must abide by one, or all by the other, without specifying which pattern is acceptable, is rather awkward.

0
James Hancock On

You are correct that events should be unsubscribed as it can also cause memory leaks if you don't.

I'm not sure if there is a suggested or standard way of doing this, but if a class needs to clear things down, then it generally implements IDisposable.

The alternative is to 'remember' to unsubscribe in the correct places - at least IDisposable makes this more obvious, especially crucial for people visiting your code at a later date.