A Closer Look At The Dispose Pattern

0 comments suggest edit

The Framework Design Guidelines has an illuminating discussion on the Dispose pattern for implementing IDisposable in chapter 9 section 3. However, there was one place where I found a potential problem.

But first, without rehashing the whole pattern, let me give a brief description. The basic Dispose Pattern makes use of a template method approach. I really like how they take this approach. Let me demonstrate…

public class DisposableObject : IDisposable
{
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    //This is the template method...
    protected virtual void Dispose(bool disposing)
    {
        if(disposing)
        {
            Console.WriteLine("Releasing Managed Resources in base class!");
        }
    }
}

This disposable class implements a non-virtual Dispose method that calls a protected virtual method. According to the guidelines, classes that inherit from this class should simply override the Dispose(bool); method like so.

public class SubDisposable : DisposableObject
{
    protected override void Dispose(bool disposing)
    {
        Console.WriteLine("Releasing Managed Resources in Sub Class.");
    }
}

Notice anything odd about this? Shouldn’t this inheriting class call base.Dispose(disposing)? The guidelines make no mention of calling the base dispose method. However, just to make sure I wasn’t missing something, I ran the following code.

using(SubDisposable obj = new SubDisposable())
{
    Console.WriteLine(obj.ToString());
}

This produces the following output:

UnitTests.Velocit.Threading.SubDisposableReleasing Managed Resources in Sub Class.

Notice that resources in the base class are never released.

Also, while I applaud the use of a protected template method to implement the dispose pattern, I think it is possible to take the pattern one step further. The purpose of using template methods is bake in an algorithm consisting of a series of steps. You provide abstract or virtual methods to allow implementations to change the behavior of those distinct steps.

When I think of the steps it takes to dispose an object using the simple pattern, it consists of the following discrete step:

  • Calling Dispose indicates object is being disposed and not being finalized
  • Call into protected Dispose(bool);
  • Protected method releases unmanaged resources
  • if disposing
    • release unmanaged resources
    • Suppress finalization

So why not codify these series of steps into the pattern. The Simple Dispose pattern might look like…

public class DisposableObject : IDisposable
{
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    void Dispose(bool disposing)
    {
        ReleaseUnmanagedResources();
        if(disposing)
        {
            ReleaseManagedResources();
        }
    }

    //Template method
    protected virtual void ReleaseUnmanagedResources()
    {}

    //Template method
    protected virtual void ReleaseManagedResources()
    {}
}

Notice that the Dispose(bool); method is now private. There are two new virtual template methods. Also note these are virtual. I did not make these abstract, since this gives the inheritor a choice on whether to implement them or not. This might seem like overkill, but it removes one more decision to be made when overriding this class. That is the goal of these patterns, to make doing the right thing automatic to the implementer.

In the previous pattern, an implementer has to remember what to do when disposing is true as opposed to it being false. Do I release unmanaged when its true? Or when its false. Certainly if you’re implementing the pattern, you should really know this down pat. But still it doesn’ hurt to make the algorithm more readable. Looking at this modified pattern, it is quite obvious what I need to do in the method ReleaseManagedResources. I probably need to add documentation to tell the overriding implementer to make sure to call base.ReleaseManagedResources().

The only open question I have with this pattern is whether or not it is safe to call base.ReleaseUnmanagedResources() from an implementing class. I need to dig into the C# specs to understand that issue fully. The issue is that from within ReleaseUnmanagedResources, you really shouldn’t touch any managed resources, because this method could be called from a finalizer thread. Is calling a method on your base class in violation of this rule?

Found a typo or error? Suggest an edit! If accepted, your contribution is listed automatically here.

Comments

avatar

4 responses

  1. Avatar for Levi
    Levi May 11th, 2006

    I had similar thoughts. In developing classes, most of the time when overriding a method, you call the base method before doing anything else. However, where construction happens from the base up, it seems that the dispose should happen in the reverse order. Calling the base dispose method at the bottom of the class, since you would logically want to destroy objects in the reverse order of their creation.
    Thoughts?

  2. Avatar for Simon
    Simon December 9th, 2007

    Nice idea, it's a shame Microsoft didn't add something like this because from my experience the dispose pattern is among the most commonly misunderstood concepts for new .NET developers.
    BTW, I think you made a typo in your steps. The last three steps should be:


    * if disposing
    - release managed resources
    - Suppress finalization


  3. Avatar for Alon Fliess
    Alon Fliess January 29th, 2008

    Template method is good only when you have one derived behavior and not a chain of derived classes. Suppose you have another class derived from the derive class. If this class overrides the ReleaseUnmanagedResources(); We will miss the call to the middle class (the derive) ReleaseUnmanagedResources().
    This is why in such scenarios you use the base class call.

  4. Avatar for Craig E. Shea
    Craig E. Shea January 24th, 2013

    Came across this only today. I looked up this pattern, once again, on MSDN. It looks like they updated the documentation a long time ago so that in the protected overridden Dispose method, base.Dispose(disposing) is called.

    However, I really like your pattern above. It is more readable and lets me know exactly what I need to do and where. I think so long as you called the base class implementation of the ReleaseXXManagedResources methods at the right place, you'd be fine. It would seem to me that you would always call the base class implementation after you've cleaned up all your own resources. It would also seem to me that greater care would need to be taken with encapsulation to prevent derived classes from deleting state from base classes which the base class may need in order for it to dispose of itself.

    Just my $.02.