CHAPTER 13 UNDERSTANDING OBJECT LIFETIME
Building Disposable Objects
As you have seen, finalizers can be used to release unmanaged resources when the garbage collector
kicks in. However, given that many unmanaged objects are “precious items” (such as raw database or
file handles), it could be valuable to release them as soon as possible instead of relying on a garbage
collection to occur. As an alternative to overriding Finalize(), your class could implement the
IDisposable interface, which defines a single method named Dispose() as follows:
public interface IDisposable
{
void Dispose();
}
When you do implement the IDisposable interface, the assumption is that when the object user is
finished using the object, the object user manually calls Dispose() before allowing the object reference
to drop out of scope. In this way, an object can perform any necessary cleanup of unmanaged resources
without incurring the hit of being placed on the finalization queue and without waiting for the garbage
collector to trigger the class’s finalization logic.
Note Structures and class types can both implement IDisposable (unlike overriding Finalize(), which is
reserved for class types), as the object user (not the garbage collector) invokes the Dispose() method.
To illustrate the use of this interface, create a new C# Console Application named SimpleDispose.
Here is an updated MyResourceWrapper class that now implements IDisposable, rather than overriding
System.Object.Finalize():
// Implementing IDisposable.
class MyResourceWrapper : IDisposable
{
// The object user should call this method
// when they finish with the object.
public void Dispose()
{
// Clean up unmanaged resources...
// Dispose other contained disposable objects...
}
}
// Just for a test.
Console.WriteLine("***** In Dispose! *****");
Notice that a Dispose() method is not only responsible for releasing the type’s unmanaged
resources, but can also call Dispose() on any other contained disposable methods. Unlike with
Finalize(), it is perfectly safe to communicate with other managed objects within a Dispose() method.
The reason is simple: the garbage collector has no clue about the IDisposable interface and will never
call Dispose(). Therefore, when the object user calls this method, the object is still living a productive life
489