One of the biggest causes of memory leaks in .NET applications (or any application), are event handlers remaining active beyond the lifetime of the parent object. Your object goes out of scope, but continues to listen for events on other objects, and hence can’t be garbage collected. Typically, your class would implement IDisposable, and you’d remove all your event handlers in that method. This works fine – if you keep track of all event handlers and remember to add the corresponding handler removal into your Dispose method.
Two more recent .NET developments which make this process easier to manage are the CompositeDisposable class, and of course IObservable, both of which can be found in the Reactive Extensions (Rx) assemblies.
CompositeDisposable is simple – it’s just a collection of IDisposable objects. When you call Dispose on your CompositeDisposable, all the items in the collection are disposed. If you create a BaseDisposable class to be used a base for all your business classes, then you can have something like the following:
public abstract class BaseDisposable : IDisposable
{
protected CompositeDisposable Disposables = new CompositeDisposable();
public bool IsDisposed { get; private set; }
public virtual void Dispose()
{
using (Disposables)
{
Disposables = null;
}
IsDisposed = true;
}
}
public class MyViewModel : BaseDisposable
{
public MyViewModel()
{
var timer = Observable.Interval(TimeSpan.FromSeconds(1))
.Subscribe(OnTimerCallback);
Disposables.Add(timer);
}
private void OnTimerCallback(long count)
{
Trace.WriteLine(count.ToString());
}
}
In the above sample, the MyViewModel class inherits BaseDisposable, so when it is disposed, anything that has been added to the Disposables collection during it’s lifetime will also be disposed – no need to add a new Dispose method with lots of event handler removals. I’ve just used a simple IObservable subscription in this example, and I haven’t implemented the Dispose pattern on my BaseDisposable – which would be a good idea in a real world scenario. In BaseDisposable, there’s also an IsDisposed property available – this can be useful for unit tests to confirm whether your object has been disposed as expected.
It’s not anything ground breaking, but it will mean you don’t have to add a Dispose method to each of your classes with lots of handler removals and disposing of child disposables. In short, cleaner and more maintainable.
IObservables work particularly well with this pattern, as each Rx subscription implements IDisposable. Concurrency, composition, and declarative syntax aside, this alone is a compelling reason to consider using Rx in place of regular event handlers in your application. Rather than specifying the handler removal in your Dispose method, just add your subscription to the Disposables collection, and the handler will be removed when your object is disposed.
