I see questions regarding the GC on a daily basis.
Dispose is a popular topic.
Let's get it in the clear.
All of us .NET programmers make use of the Garbage Collector (GC) – some
without knowing so. You have to familiarize yourself with the internals of the
GC if you wish to create scalable components – there is no other option. Even
though it does all its bits automagically, you can harness a lot of its power by
understanding three basics:
Dispose, and the Destructor protocol in managed code. I will not
be going into the finer details of how the GC does its job, but rather explain
how you as a programmer can (and should) optimize your objects for the GC.
When an object is instantiated, the GC allocates memory for it on the managed
heap. If the class contains a
Finalize method, the object
is also enlisted in the “finalisation queue”. When this object is no longer
needed, its memory will be reclaimed (freed) by the GC. If the object is
enlisted in the finalization queue, its
will be called before discarding of the object. The purpose of the
Finalize method is to release any resources (like a database
connection, or a handle on a window) that might be in use by your object.
Since the GC decides when it is best to clean up objects (and it does a damn
fine job in doing so!), you have no way of telling when exactly
Finalize will be called.
Finalize is also a
protected member and can thus not be called explicitly.
Does this mean that cleaning up your object is left entirely in the hands of the
Of course not. For increased performance, it is best to cleanup your unused
resources immediately after using them. For instance, as soon as you have
retrieved your data through a database connection, the connection should be
discarded of since it eats up system resources like memory, which could be
better utilized by objects that you do in fact need. For this reason, an object
can implement the
Dispose method (by implementing the
IDisposable interface). Calling the
method on an object does two things. Firstly, it cleans up any resources that
were in use by your object. Secondly, it marks the object so that the GC would
not call its
Finalize method when it collects it – the
resources have been cleaned up already in your
method. This way, you save the overhead of the GC’s call to
Finalize, and you can clean up your object at the most
How to implement Finalize and Dispose
Now that you know the reasons for these two methods, let’s see how to
In managed code, you cannot override or even call
Finalize – it is implicitly generated (in IL) by the compiler if
you have a destructor for your object. In other words, the following:
Translates to the following:
protected override void Finalize()
As you can see, the method also calls
Finalize on its
parent type, and the parent type will call
Finalize on its
parent type – the whole hierarchy of your object is thus cleaned up. It is
important to understand that you should only have a destructor for your class if
it is really necessary, since calling
enlisting objects that implement
Finalize in the
finalization queue by the GC, has significant performance implications.
Dispose method is publicly callable. (I’ll explain
the overload that accepts the
boolean parameter later).
Here is an example of an object that implements
public class MyClass : IDisposable, BaseClass
disposed = false;
public void Dispose()
protected virtual void Dispose(bool disposing)
disposed = true;
When you explicitly call
Dispose() on your object, both
managed- and unmanaged resources will be cleaned up. When the GC cleans your
object (instead of you), only unmanaged resources will be cleaned, since the
managed resources will be cleaned up by the GC when necessary.
Don’t reference any managed resources in your
method (destructor), since Finalizers are not called in any particular fashion,
and the object you reference may thus be disposed of already. In such a case,
Finalize method will fail. If you *do* reference any
managed resources downward in your object hierarchy, those objects will not be
finalized with the current GC collection, and performance will suffer.
When calling any method on your object, it is necessary to first check if the
object has been disposed. So a method in
MyClass would look like
public void MyMethod()
throw new ObjectDisposedException();
In a further article, I will dive deeper into the GC, and explain the
implications of threading on your
(This article is also published on my
[Update: Check GC 102 for further
notes on programming for Garbage Collection.]