Now I understand that when I have finished with a resource that implements IDisposable, I should call the Dispose() method to clean up the resources.
To what extent should I be doing this.
My example is:
I am creating a NotifyIcon in code, so I do something like this:
var icon = new Icon(...);
var contextMenu = new ContextMenu(...);
var contextMenuButton1 = new MenuItem(...);
var contextMenuButton2 = new MenuItem(...);
var contextMenuButton3 = new MenuItem(...);
// ...
var notifyIcon = new NotifyIcon(...);
All of these have a Dispose() method. Normally I would only keep reference to the notifyIcon and just dispose that.
However, it won't dispose of the Icon or the Context Menu or its items, so should I actually be keeping a reference to everything, or at least have a List<IDisposable>?
OR can I assume because of the scope of these that the garbage collector will call dispose on these for me (when I dispose of the NotifyIcon)?
Generally, that's what the using statement is for, eg.:
The using statement calls the Dispose method as soon as it ends (and even if there's an exception inside, it will still properly dispose of the variable). You can even "chain" them to reduce nesting:
You want to call Dispose as soon as you can. If you don't, it will still be called at some point, usually during finalization of the object, but that might already be too late (for example, disposing of a file handle will allow another file handle to be opened, while if you don't dispose of it soon enough, the second call will throw an exception).
The reason there's a Dispose method in the first place is because Icon has some native resources in the background (it uses a native Icon object, this is all related to Windows and GDI+). These resources are "scarce" (a better example is the file handle), and as such you don't want to wait for the GC to collect them eventually - that's more costly (finalization has a non-trivial cost if done extensively) and can block access to the resource (even with the Icon, I remember an issue where you could only allocate so many native bitmaps per process, then you're starved).
If you don't care about the cost, and if the resource isn't scarce enough to matter, and if the
usingorDisposeis more trouble than it's worth - you don't have to call Dispose. It will be called eventually.As examples of where you should pretty much always call dispose manually: Files, Streams, Sockets, large blocks of native memory.