Making sure that your application is disposing of any unwanted resources has always been part of the ugly plumbing work of writing software. Although .NET "helps" with this - by providing a non-deterministic Garbage Collector - it can actually muddy the waters a little. Now, instead of having to implement a Destructor in each class, most of the time you can let the framework deal with it.
The tricky part - and the reason I'm writing this blog - is remembering the specific scenarios when you need to, and when the framework will take over.
The general guidance is that you only need to implement IDisposable when dealing with unmanaged resources. This is because the framework has no way of tracking this, and you need to do it yourself. However, there are other scenarios where you might need more control.
A specific scenario would be if we had a class which had hooked into events provided by a global static or singleton class. This singleton would likely not be disposed of until the application is shut-down (although obviously every case is different). Because the delegate keeps a reference to our class, it would keep it alive until the singleton is disposed. It is highly likely we want to free our class before this. Whether we do this as part of implementing the IDisposable pattern, or use Init() and Unit() methods, is still up for debate.
In the following scenario, only ListForm and NavBarControl is required to implement IDisposable (because it is a Form):

Because this is a self-contained object graph, once we free our reference from ListForm, the GC will be able to free all the objects within this graph.
HOWEVER, if, say, ListFormController were to hook up an event handler to an object outwith this graph, then we would be in trouble - because it would not be freed and therefore keep it's referenced items alive.
You can find out more about the IDisposable pattern here.