Garbage collection: GC reclaims the memory used by the object when the object is referenced no more.
Dispose: a method from the IDisposable interface that is to release all managed and unmanaged resources when the programmer calls it (either directly or indirectly via a using block).
Finalizer: a method to release all unmanaged resources. Called by the GC before reclaiming the memory.
Managed resource: any .NET class that implements the IDisposable
interface, like Streams and DbConnections.
Unmanaged resource: the stuffing wrapped in the Managed Resource classes. Windows handles are the most trivial examples.
Now to answer your question:
GC keeps a list (Finalization Queue) of all objects the class of which declares a Finalizer (~ClassName in C#). Objects are put in this queue upon creation. GC runs periodically to check whether there are any objects inaccessible from the program. It then checks if any of the inaccessible objects are referenced from the Finalization Queue, and puts these in another queue called the Freacheable queue, while the rest are reclaimed. A separate thread is used to run the Finalize methods of objects in the Freacheable queue.
The next time GC runs, it will find that some of the objects previously in the Freacheable queue are already Finalized thus are ready for reclaiming. Note that GC needs at least two cycles (or a lot more if there is a lot of Finalization to do) to get rid of an object with a Finalizer, which incurs some performance penalties.
The SuppressFinalize
method simply sets a flag in the object header which indicates that the Finalizer does not have to be run. This way GC can reclaim the memory of the object right away. As per the definition above, the Dispose
method does the same thing as the Finalizer (and more), so if it is executed then Finalization is not neccessary any more. Using the SuppressFinalize
method, you can save some work for the GC by notifying it about this fact. Additionally, now you don't have to implement checks in the Finalizer to avoid double releasing. The only problem with Dispose
is that is is not guaranteed to run, because it is the programmer's responsibility to call it, that is why sometimes we need to bother with Finalizers.
That being said, it is only very very rarely that you need to write a Finalizer, because for the vast majority of the usual unmanaged resources a managed wrapper already exists, and managed resources are to be released by calling their Dispose
methods from your own Dispose
method, and from there only! In finalizers you must never call a Dispose method.
Further reading: