First of all, IDisposable.Dispose
and GC isn't about the same thing.
GC will clean up memory usage, IDisposable.Dispose
is used to deterministically free resources, like file handles, database connections, network connections, etc.
Let's tackle finalization first.
If an object declares a finalizer, the object is treated specially when GC comes around to freeing it from memory. The object is, instead of just being freed at once, put on a separate list.
In the background, a finalization thread is running through this list and calling the finalizer methods of the objects on this list. Once the finalizer method has been called, the object is removed from the list.
The point here is that while the object is on this list, it is not eligible for collection. This means that an object that has a finalizer, once it becomes eligible for collection, will temporarily transition into a state where it is no longer eligible for collection, but pending finalization. Once the object is discovered again, after the finalizer has run and it has been removed from this list, then it is being freed from memory.
GC.SuppressFinalize
is just a way for an object to say that "the finalizer no longer needs to run, if you discover that this object is eligible for collection, just free it at once".
IDisposable.Dispose
, on the other hand, once implemented by an object, is not entirely related to the garbage collector. There is nothing built into the GC system that will ensure that the Dispose
method is called. This means that an object that has a Dispose
method can easily be freed without Dispose
ever being called.
Also, calling Dispose
does not in any way make the object eligible for collection. The only way to make an object eligible for collection is to remove all strong references to it, usually by letting local variables going out of scope (method returns) or by removing any references to the object from other objects (like lists, event handlers, etc.)
The "link", if you want to call it that is that an object that internally has such a resource will typically implement a finalizer, if the resource is unmanaged. If the resource is a managed one, like a FileStream
object, then that object will take care of finalization, if needed, by itself. However, if you're holding on to unmanaged resources, like file handles you have retrieved via P/Invoke, then you should implement a finalizer.
Typically, both the finalizer and IDisposable.Dispose
for that object will clean up that resource, and its then typical for Dispose
to call GC.SuppressFinalize
to say that "I've taken care of it, you can just free the object if it is eligible for collection."
However, if you just call Dispose
, but still keep a reference to the object (event handler, static fields, local variables, etc.) then the object is not yet eligible for collection and will not be freed.
So, to summarize:
- Calling
Dispose
is typically done to free up resources (unmanaged or managed). It does not in any way influence whether GC can collect the object, or when it will be done.
- The only way to make an object eligible for collection is to explicitly lose all strong references to it.
- A finalizer is called by GC, usually implemented to free unmanaged resources.
- An object that is eligible for collection, but has a finalizer, will temporarily be put on a list (and thus no longer be eligible for collection) until the finalizer has been executed
Bonus questions:
What do you think will happen if:
- A finalizer hangs? (There is typically (that is, to my knowledge) only one finalizer thread, if it hangs, what happens to the rest of the objects on that list?)
- An object makes itself uneligible for collection as part of its finalizer (typically by inserting itself into a static field). The finalizer has run, and there is a mark for that, so the finalizer will not automatically re-run once the object again becomes available for collection. There are other methods in the GC object that can re-register it for finalization though.
Hope this answered your question, if not, please leave a comment or clarify your question and I'll edit my answer.