You're missing the point. Whenever any class implements IDisposable
, you should call Dispose
when you're done with it.
Whether the class uses unmanaged resources or not is internal to the class, you shouldn't care about it at all. Every class that uses unmanaged resources should also have a finalizer that clears up those unmanaged resources if you didn't dispose of the class explicitly. Dispose
just allows you to clean its resources (both managed and unmanaged, though this doesn't necessarily mean freeing up the memory immediately) in a more deterministic and immediate fashion. For example, Dispose
ing a FileStream
will release the file handle immediately, while if you don't Dispose
(or Close
), the file will be opened until the next collection and finalization.
EDIT:
To show that Dispose
may also be necessary to clean up managed resources, we only have to look at event handlers. In particular, the case when you're subscribing on an event of a class that has a longer lifetime than you do:
var control = new MyHelperControl();
MyParentForm.Click += control.DoSomething();
Now, even if control
goes out of scope, it will survive as long as MyParentForm
- it's still referenced by the event handler. The same problem grows to absurd proportions when the parent has the same lifetime as the whole application - that's can be a huge memory leak. An example would be registering event handlers on the main form of an application, or on a static event.
There might also be other things that happen in the Dispose
. For example, again with Windows forms, when you call Dispose
on a Control
, a whole lot of things happen:
- All the unmanaged resources are released. Since Winforms controls are wrappers of the native controls to an extent, this is usually a lot of resources - the control itself, any pens, brushes, images... all of those are native resources. They will also be released if you forget a
Dispose
, since they all have finalizers, but it might take more time - which is especially painful when you create and destroy a lot of those objects. For example, there's a limited supply of GDI+ object handles, and if you run out, you get OutOfMemoryException
and you're out.
- Dispose of all sub-controls.
- Remove any context menu handlers (remember, context menu is a separate component that's only linked to another control).
- Remove any data bindings.
- Remove itself from the parent container, if any.
- If the control is a window with its own message loop, kill the message loop.
The funny part is that the unmanaged resources matter the least, really - they always have a finalizer. The managed resources are trickier, because you're more or less forbidden to handle managed references in a finalizer (because they might have already been released, or they might be in the middle of being released, or they might start being released in the middle of your finalizer... it's complicated). So doing MyParentForm.Click -= this.OnClick;
is not a good thing to have in your finalizer - not to mention that it would require you to make every such class finalizable, which isn't exactly free, especially when you expect the finalizer to actually run (when you do a Dispose
, the GC is alerted that this instance no longer needs a finalization).