Ever wondered why the hell .Net has more than one way of getting rid of stuff. I was wondering the same thing today. After I got back from the hospital for bashing my head against Microsoft's documentation, I look around a little on the aether and finally, began to see the light. To all those, who like me, are MS documentation impaired, here's what it means (in the mind of Tallies, that is)...
Finalize
Finalize is a protected method inherited from Object. If you reference and use instances of other objects in your class (ie. via member variables), you need to drop those suckers in the Finalize method. Now in C# and Managed C++, you don't, however, override Finalize (in VB you do). You implement a destructor (which really isn't a destructor at all!), like so:
public class MyObject
{
void MyObject(){}
~MyObject()
{
//destroy all those nasty resource hogs here....
}
}
Now, that's all good and well, but there's a catch. When the GC runs and it finds an object that is dead, but still needs to be finalized (which you can't do yourself in code, ie. you cannot call a “destructor” or (in VB) the Finalize method), it does NOT reclaim the space used by that object. In fact it, it keeps it alive (and makes sure any internal references are also kept alive!) and adds it to a special queue ('freachable' queue). This finalizer thread (every .Net process has one), runs through that queue (when it likes!) and finalizes the objects in it. This simply means that any object still needing finalization will survive at-least one GC run. Not always desirable.
Dispose
But wait, all is not lost. The uber-geeks at Redmond knew that anybody with some C++ background, or who likes deterministic memory management would be running for the hills. So they created the IDisposable Interface. When your class implements this interface, you have to implement only one method: Dispose(). This method *should* be called by clients of your object. “But wait!”, I hear you say, “This does nothing for the finalize situation above!”. No it doesn't, unless off course if you call GC.SuppressFinalize in your dispose method, which tells the GC that your object does not need to be finalized, and can be collected.
It's a little open to “abuse”, if I can call it that. This is because, though it's encouraged to call dispose when available, it's not enforced, so your object might still linger around longer than needed (By show of hands, who ,reading this, ALWAYS calls Dispose() on SQLConnection? Oh, it has a Dispose()?). A good strategy, when implementing IDisposable, is to have one common clean up method, called from Dispose and your “destructor”, which cleans up all those nasty monsters lying around and the calling GC.SuppressFinalize in the Dispose() method.
Note that I've skipped a lot of detail, and may be outrightly wrong in some places (due to lack of detail), but I believe the gist of it is accurate enough. There are considerations to keep in mind when deciding whether you should implement IDisposable or not. In short, use IDisposable whenever you have really resource hungry things like db connections or streams etc lying around. My rule of thumb: If you're using objects in your class that implements IDisposable, then so should you.
Anyways, I hope this was somewhat insightful and not all together inaccurate! ;-) Oooohh, long post.... bad blogger, BAD...