Posted by: Cirilo Meggiolaro | 01/22/2009

Tip of the day #100 – Implementing the Dispose pattern

How many times have you coded calls to the Dispose methods on objects like DataSet, FileStream and others? If you haven’t coded so much, turn on the red light and start releasing resources. If you are used to do this, keep using it.

The primary idea about the use of the Dispose method is to have a standard method where you must release unmanaged code (native resources and COM objects) that are not allocated on the managed heap (not handled by the Garbage Collector). It does not mean that when you implement the Dispose method this will be called by magic. There is no magic and if the Dispose method is not explicitly called the runtime will not call it.

All built-in classes that expose the Dispose method implement the IDisposable interface and today we are going to check how to implement the IDisposable interface and the Dispose pattern on your application’s objects.

How to…

The first important thing that you need to be aware of is that once you request an object to be released it is included in the finalization queue. Objects in the finalization queue will have their Finalize method invoked. Finalizer methods are costly and the main reason to use Dispose method instead of Finalize method is that there is no guarantee that the Finalize method will be invoked, by a lot of reasons such as the unload of the application domain. Other than that you don’t want to release resources twice, right?

So, to avoid that, after release the resources on your object from within the Dispose method let the Garbage Collector know so the object will be removed from the finalization queue. The SuppressFinalize helps us to achieve that goal:

GC.SuppressFinalize(this);

The second important point is to keep track that your object has been cleaned up. A private Boolean flag will help you:

private bool _disposed = false;

Make sure that if your client code does not call your Dispose method, you have a plan for releasing the unmanaged code invoking from your object class destructor, the Dispose method. When you invoke the Dispose at this point, release only unmanaged code.

Ok, but how do we handle this situation? The answer is to create two overloads for the Dispose method:

  • A private overload that accepts a Boolean flag as parameter that indicates whether the call is coming from a dispose operation request or from the destructor;
  • A public overload without parameters that will be called from the client code. This overload will invoke the private overload passing true as parameter indicating that it is a dispose request operation. After that the SuppressFinalize method will be called to remove the object from the finalization queue.

The following code is commented and demonstrates a class implementing the IDisposable interface and the Dispose pattern. The FileStream object is just for example purposes:

#region Attributes
/// <summary>
/// File stream object
/// </summary>

FileStream _stream = null;

/// <summary>
/// This private member flag that specifies
/// whether the dispose has been called.
/// </summary>
private bool _disposed = false;
#endregion

#region Constructor / Destructor
/// <summary>
/// Default constructor.
/// </summary>
/// <param name=”path”>Stream path.</param>
/// <param name=”mode”>File mode.</param>
public MyDisposableClass(string path, FileMode mode)
{
    if (_stream == null)
        _stream = new FileStream(path, mode);
}

/// <summary>
/// Class destructor.
/// </summary>
~MyDisposableClass()
{
    // The call in destructor must be used only
    // for unmanaged resources release.

    Dispose(false);
}
#endregion

#region Write
/// <summary>
/// Write content to the stream.
/// </summary>
public void Write(byte[] content)
{
    if (_disposed)
        throw new ObjectDisposedException(“MyDisposable class has been disposed.”);

    // Do something
}
#endregion

#region IDisposable Members
/// <summary>
/// Public Dispose overload.
/// </summary>
public void Dispose()
{
    // Calls overload method to release managed resources.
    Dispose(true);

    // Calling the suppress finalize remove
    // this object from the finalization queue.
    
GC.SuppressFinalize(this);
}

/// <summary>
/// Private Dispose overload.
/// </summary>
/// <param name=”isDisposing”>Indicates whether the call comes from
/// a dispose request (true) or from the finalizer (false).</param>
private void Dispose(bool isDisposing)
{
    // Checks if the object has not been disposed yet.
    if (!_disposed)
    {
        // Checks if the call comes from a dispose
        // request (true) or from a finalizer (false).
        
if (isDisposing)
        {
            //Dispose managed resources.
            if (_stream != null)
            {
                _stream.Dispose();
                _stream = null;
            }
        }

        // Releases unmanaged resources here.
    }

    // Sets a flag indicating that the
    // object has been disposed.
    
_disposed = true;
}
#endregion


Responses

  1. Congratulations for the 100th issue on Tip of the Day!

    I’ve been following your blog for a long time now and I’m impressed with all the useful information you provide for all of us.

    Thank you!!
    Keep up the good work…

  2. I agree with Thiago. Applause!


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Categories

%d bloggers like this: