IDisposable, Done Right

IDisposable is a standard interface in the .NET framework that facilitates the deterministic release of unmanaged resources. Since the Common Language Runtime (CLR) uses Garbage Collection (GC) to manage the lifecycle of objects created on the heap, it is not possible to control the release and recovery of heap objects. While there are methods to force the GC to collect unreferenced objects, it is not guaranteed to clear all objects, and it is highly inefficient for an application to force garbage collection as part of the service control flow.

Implementing IDisposable

Despite IDisposable having only a single method named Dispose to implement, it is commonly implemented incorrectly. After reading this blog post it should be clear how and when to implement IDisposable, as well as how to ensure that resources are properly disposed when bad things happen (also knows as exceptions).

First, the IDisposable interface definition:

public interface IDisposable
{
    void Dispose();
}

Next, the proper way to implement IDisposable every single time it is implemented:

public class DisposableClass :
    IDisposable
{
    bool _disposed;

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    ~DisposableClass()
    {
        Dispose(false);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (_disposed)
            return;

        if (disposing)
        {
            // free other managed objects that implement
            // IDisposable only
        }

        // release any unmanaged objects
        // set the object references to null

        _disposed = true;
    }
}

The pattern above for implementing IDisposable ensures that all references are properly disposed and released. Using the finalizer, along with the associated dispose methods, will ensure that in every case references will be properly released. There are some subtle things going on in the code, however, as described below.

Dispose()

The implementation of the Dispose method calls the Dispose(bool disposing) method, passing true, which indicates that the object is being disposed. This method is never automatically called by the CLR, it is only called explicitly by the owner of the object (which in some cases may be another framework, such as ASP.NET or MassTransit, or an object container, such as Autofac or StructureMap).

~DisposableClass

Immediately before the GC releases an object instance, it calls the object’s finalizer. Since an object’s finalizer is only called by the GC, and the GC only calls an objects finalizer when there are no other references to the object, it is clear that the Dispose method will never be called on the object. In this case, the object should release any managed or unmanaged references, allowing the GC to release those objects as well. Since the same object references are being released as those that are released when Dispose is called, this method calls the Dispose(bool disposing) method passing false, indicating that the references objects Dispose method should not be called.

Dispose(bool)

All object references and unmanaged resources are released in this method. However, the argument indicates whether or not the Dispose method should be called on any managed object references. If the argument is false, the references to managed objects that implement IDisposable should be set to null, however, the Dispose method on those objects should not be called. The reason being that the owning objects Dispose method was not called (Dispose(false) is only called by the finalizer, and not the Dispose method.

Overriding Dispose

In the example above, the Dispose(bool disposing) method is declared as protected virtual. This is to allow classes that inherit from this class to participate in the disposable of the object without impacting the behavior of the base class. In this case, a subclass should override the method as shown below.

public class SubDisposableClass : 
    DisposableClass
{
    private bool _disposed;

    // a finalizer is not necessary, as it is inherited from
    // the base class

    protected override void Dispose(bool disposing)
    {
        if (!_disposed)
        {
            if (disposing)
            {
                // free other managed objects that implement
                // IDisposable only
            }

            // release any unmanaged objects
            // set object references to null

            _disposed = true;
        }

        base.Dispose(disposing);
    }
}

The subclass overrides the method, releasing (and optionally disposing) object references first, and then calling the base method. This ensures that objects are released in the proper order (at least between the subclass and the base class, the proper order of releasing/disposing objects within the subclass itself is the responsibility of the developer).

Exceptions, Happen

Prior to .NET 2.0, if an object’s finalizer threw an exception, that exception was swallowed by the runtime. Since .NET 2.0, however, throwing an exception from a finalizer will cause the application to crash, and that’s bad. Therefore, it is important that a finalizer never throw an exception.

But what about the Dispose method, should it be allowed to throw an exception? The short answer, is no. Except when the answer is yes, which is almost never. Therefore, it is important to wrap any areas of the Dispose(bool disposing) method that could throw an exception in a try/catch block as shown below.

protected virtual void Dispose(bool disposing)
{
    if (_disposed)
        return;

    if (disposing)
    {
        _session.Dispose();
    }

    try
    {
        _channelFactory.Close();
    }
    catch (Exception ex)
    {
        _log.Warn(ex);

        try
        {
            _channelFactory.Abort();
        }
        catch (Exception cex)
        {
            _log.Warn(cex);
        }
    }

    _session = null;
    _channelFactory = null;

    _disposed = true;
}

In the example, session is a reference to an NHibernate ISession and channelFactory is a reference to a WCF IChannelFactory. An NHibernate ISession implements IDisposable, so the owner must call Dispose on it when the object is no longer needed. In the case of the IChannelFactory reference, there is no Dispose method, however, the object must be closed (and subsequently aborted in case of an exception). Because either of these methods can throw an exception, it is important to catch the exception (and, as shown above, log it for troubleshooting or perhaps just ignore it) so that it doesn’t cause either the Dispose method or the object’s finalizer to propagate the exception.

Constructor Exceptions

On a related topic, when an object’s constructor throws an exception, the runtime considers the object to have never existed. And while the GC will release any object allocated by the constructor, it will not call the Dispose method on any disposable objects. Therefore, if an object is creating references to managed objects in the constructor (or even more importantly, unmanaged objects that consume limited system resources, such as file handles, socket handles, or threads), it should be sure to dispose of those resources in the case of a constructor exception by using a try/catch block.

While one might be tempted to call _Dispose_ from the constructor to handle an exception, don’t do it. When the constructor throws an exception, technically the object does not exist. Calling methods, particularly virtual methods, should be avoided.

Of course, in the case of managed objects such as an ISession, it is better to take the object as a dependency on the constructor and have it passed into the object by an object factory (such as a dependency injection container, such as Autofac) and let the object factory manage the lifecycle of the dependency.

Container Lifecycle Management

Dependency injection containers are powerful tools, handling object creation and lifecycle management on behalf of the developer. However, it is important to have a clear understanding of how to use the container in the context of an application framework.

For example, ASP.NET has a request lifecycle for every HTTP request received by the server. To support this lifecycle, containers typically have integration libraries that hook into the framework to ensure proper object disposal. For instance, Autofac has a number of integration libraries for ASP.NET, ASP.NET MVC, ASP.NET Web API, and various other application frameworks. These libraries, when configured into the stack as HttpModules, ensure that objects are properly disposed when each request completes.

Conclusion

The reason for IDisposable is deterministic release of references by an object (something that used to happen manually with unmanaged languages by calling delete on an object). Implementing it both properly and consistently helps create applications that have predictable resource usage and more easy to troubleshoot. Therefore, consider the example above as a reference point for how objects should be disposed.

References:
- Autofac Web Integration
- Microsoft Documentation

Bonus:
- Resharper Template

Related Articles:

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Chris Patterson

Chris is a senior architect for RelayHealth, the connectivity business of the nation's leading healthcare services company. There he is responsible for the architecture and development of applications and services that accelerate care delivery by connecting patients, providers, pharmacies, and financial institutions. Previously, he led the development of a new content delivery platform for TV Guide, enabling the launch of a new entertainment network seen on thousands of cable television systems. In his spare time, Chris is an active open-source developer and a primary contributor to MassTransit, a distributed application framework for .NET. In 2009, he was awarded the Most Valuable Professional award by Microsoft for his technical community contributions.
This entry was posted in c#. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • jer0enh

    Yuk. I’d hoped that we had moved beyond this monstrosity…. http://www.codeproject.com/Articles/29534/IDisposable-What-Your-Mother-Never-Told-You-About

    • http://twitter.com/PhatBoyG Chris Patterson

      IDisposable is still alive and well, that’s for sure.

      • jer0enh

        Of course it is, I’m not arguing with that. We need deterministic disposal and obviously in some cases the full dispose pattern as you describe it is warranted. However, implementing this full pattern by default on every class that implements IDisposable hurts readability and as others also have said, a Finalizer is almost never needed and can actually introduce other (performance) issues. Please at least skim through the article on codeproject I linked to, it’s well worth a read.

        • jer0enh

           (I meant to say skim through part II of the article which offers some simple advice that greatly simplifies the implementation of IDisposable resources)

  • http://jwatson3d.myopenid.com/ John

    Hi Chris, Thanks for the detailed article! FYI, I tried downloading the R# template but the link doesn’t work.

  • Peter-John Lightfoot

    Some errata, if I may… CLR is for *Common* Language Runtime (not Command). 

    Also, it is inadvisable to create finalizers by default if the class does not hold unmanaged resources (or managed resources that in turn hold unmanaged resources). Even when a managed IDisposable object was not disposed, it will get decently collected by the GC when it goes out of scope. – This is because an object with a finalizer has the additional overhead of being registered as finalizable with the GC (which in turn means additional overhead of being monitored and scheduled for finalization).

    At the very least, finalizable objects should suppress finalization from their Dispose method, in the case that the object was properly disposed before going out of scope. This would shave of the second half of the overheads mentioned above.

    Nevertheless… great post and a good starting point for understanding proper memory management practices in .Net

    For a follow-up read, consider my blog post http://pj.lightfoot.cc/2011/12/02/a-base-implementation-of-system-idisposable/ for a strong implementation of IDisposable… and if you’re still interested to know more click through to Joe Duffy’s article (link from mine).

  • http://www.facebook.com/profile.php?id=1022598010 Michael Christiansen

    Thanks for the article, this was good information. One
    question: If the Finalizer gets called before Dispose wouldn’t that be
    considered a bug? When you instantiate a class that implements IDisposable my understanding is that you
    should take pains to make sure Dispose is called before it goes out of scope.
    At the least it seems like it would be worth logging a big fat error when the Finalizer is hit and dispose wasn’t called. Otherwise your unmanaged resources don’t get cleaned up until the gc
    gets around to it, potentially on a different thread, and in unpredictable order when you have more than one disposable
    object.

    • Peter-John Lightfoot

      The *only* reason for a finalizer should be to ensure that Dispose is called, in case your consumer didn’t do this as they should have. This means two things: 1) the finalizer should not do anything other than call Dispose(false), and 2) if Dispose(true) is called, your implementation should call GC.SuppressFinalize(this);

  • Andy

    Interestingly, writing “implements IDisposable” on a class in VB.Net and hitting enter generates all the pattern’s code for you.

    I always wondered why C# didn’t.

  • Jason Bock

    One other thing…

    If your object is disposable, you should also throw ObjectDisposedException whenever someone tries to use any member on that object after Dispose() was called:

    http://msdn.microsoft.com/en-us/library/system.objectdisposedexception(v=vs.71).aspx
    http://stackoverflow.com/questions/668440/handling-objectdisposedexception-correctly-in-an-idisposable-class-hierarchy

    Regards,Jason

  • Samuel Langlois

    This article is very useful, thanks. I didn’t understand what the disposing parameter really meant, now I do!

  • peterritchie

    You don’t mention that the finalizer is only needed if you need to free unmanaged resources (in .NET 4.5, it’s *very* rare that you need to free unmanaged resources).  If you have a finalizer and don’t have unmanaged resources then you’re introducing needless “performance costs associated with Finalize methods”. (http://bit.ly/RnZL0k) i.e. this pattern should only be used by classes that always need to free unmanaged resources–hence the title of the reference MSDN article “Implementing Finalize and Dispose to Clean Up *Unmanaged* Resources”.

    The GC will collect any managed resources that an object uses when that object has no more references, finalizer isn’t needed for that.  If you want to deterministically free those managed resources, then be sure Dispose is called (again, no finalizer is needed for that).When you realize you don’t need the finalizer (about 99% of the time) then you no longer need a boolean in the Dispose(bool) method.  Once you don’t need that, you don’t really need the 2nd Dispose and subclasses can simply call the IDisposable.Dispose implementation–making the implementation much easier and much less likely for human error.

    • Mike Ward

      Agree. If you don’t have unmanaged resources, skip the full dispose pattern and just implement a simple dispose. 

      • sisl developer

        That’s why you have so many bugs

      • AstroArch

        Wow.  I can’t believe you are seriously suggesting that someone write LESS code.  I mean, what if you might need more later?  Sisl Dev is right.  That’s why your code is so buggy.  There is this concept called Separation of Concerns (SoC).  If you want less bugs, you should employ a SoC framework.  Do something like this:

        First, describe an interface where the dispose responsibility lives:

        public interface IDisposer : IDisposable
        {    void Initialize(Action disposeCallback);
        }

        Implement it like so:

        public class Disposer : IDisposer {
            private readonly Action _disposeCallback;

            public void Initialize(Action disposeCallback) 
            {
                _disposeCallback = disposeCallback;
            }

            public void Dispose() 
            {
                _disposeCallback(true);
            }
        }

        Now, because of a concept called Dependency of Concerns (DoC), you can’t just “new” up one of those disposers… you need a factory to do it for you:

        public interface IDisposerFactory : IDisposable
        {
            IDisposer Create(Action disposeAction);
        }

        Now that you have the IDisposerFactory, you can implement your class as so:

        pubic class YourBuggyClass : IDisposable
        {
            private readonly IDisposer _disposer;
            public YourBuggyClass(IDisposerFactory disposerFactory)
            {
                _disposer = disposerFactory.create((disposing) => DoRealDispose(disposing));
            }

            private void DoRealDispose(bool disposing) {
                // dispose your stuff here
            }

            public void Dispose() 
            {
                _disposer.Dispose();
            }
        }

        Viola!  Your buggy class is now less buggy!  You should do it this way every time.  That way, when you need to separate your disposal concerns from your class concerns, you have a pure architecture.

        Good luck, you’ll need it!

        • German Architecture Team

          I wish I could flag this……as awesome. This is a dev who loves the craft and really understands how hard it is to write good software.

        • guessit

          Why is disposing not a class concern? The DoRealDispose is still there.
          Why did you  favor an dependency on the constructor?

          Still missing  dispose(false) in the finalizer.

        • Just Saying

          At the end of the day, in your implementation the dispose responsibility is still “living” in YourBuggyClass.  You’re just going around your elbow to get to it.  Your interface by itself doesn’t separate anything.  Perhaps there is a clue in the monadic Dispose method.  The boolean “disposing” suggests that maybe this should really be two functions.

          PS: Being obnoxious and being condescending doesn’t make you a better developer.

          • Hmmm

            I think you might have been lured by a troll. AstroArch, as in Astronaut Architect? I think AstroArch is having a joke of it. Kind of funny, IMO, assuming it is a joke.

          • Steve Walsh

            Good observation (I hope!). The scary thing is that I know quite a few devs who would write that sort of code and make that sort of comments…

        • http://www.facebook.com/tec.goblin Tec Goblin

          “I can’t believe you are seriously suggesting that someone write LESS code.” I try to understand if this is sarcasm or not.

        • Sergey

          This is scary, I pity people working with you… Continue writing vague, performance-hitting and hard-to-read code. And conveying it with such vanity…

        • Mark Lindell

          That’s awesome… hey, wait a minute…

        • http://www.webdesigningcourse.in anupriya26

          Agree this seems to interesting and much easier! Hope by doing so will not cause any bugs. Let me try it!!

          PHP training in Chennai

        • HB

          I’d say that is “overarchitected”. It should be the class’s responsibility to dispose of its own objects. That responsibility should not be given off to the consumer. Encapsulated within the current class is so much more robust.

    • http://blog.hackedbrain.com Drew Marsh

      +1000. Someone just linked this and I was replying to explain that it’s actually terrible advice for types that would only contain other managed, disposable types. Adding a finalizer to a class comes with steep GC implications that you do not want to have unless you are working with unmanaged resources.

  • Romeblue

    Command Language Runtime (CLR).Command?

    • http://twitter.com/PhatBoyG Chris Patterson

      Oops.

  • Don

    @Chris Patterson
    I am so confused. So many comments and so many different opinions. After all, is your approach “the right one”?

  • http://twitter.com/jcdickinson Jonathan C Dickinson

    I agree with peterritchie. Only implement the finalizer if you directly control unmanaged resources (which you should **NEVER EVER** be directly controlling anyway, see SafeHandle (http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.safehandle.aspx ), or obscure scenarios like temporary files.

    The reason it is important is because of the finalizer queue (http://msdn.microsoft.com/en-us/library/0s71x931.aspx ). The GC needs to iterate over this thing every time it does a pass. Filling it up with junk that doesn’t need to be there isn’t a good idea.However, you should always provide Dispose(bool) as your inheritors might find they need a finalizer (you don’t need one because you know that you should be using SafeHandle).

    Your code is also susceptible to a race condition, you could be double-disposed in threaded scenarios. Considering that the thread-safe code is shorter it makes more sense to always do it that way.

    Basically, you are looking for this: https://gist.github.com/4196875

    • http://twitter.com/PhatBoyG Chris Patterson

      If multiple threads are sharing a disposable resource, a parent or other thread should be responsible for disposing of it once the consuming threads have exited. Otherwise, a thread could dispose of something that another thread might still be using.

      • http://twitter.com/jcdickinson Jonathan C Dickinson

        Did you read the comment?

        Firstly, if your library is being consumed by a 3rd party you can’t guarantee that your best practices are being adhered to. There are bad programmers out there.
        If your library is not being consumed by a 3rd party you can’t guarantee that your best practices are being adhered to, especially in threaded situations. Good programmers make mistakes.Throwing an ObjectDisposedException is better than double-disposing in absolutely every situation. Rolled back that transaction twice? “Yeah, but the controlling thread was in charge of disposing that object.” Try telling that to a customer who just lost millions to a bug that is easily avoided by simply not using a `bool`. At the very least it’s a lot more explanatory than a FileNotFoundException in a bug report.I don’t put hypothetical walls up around myself, I put up real barriers – and you are irresponsible if you don’t because there is a massive difference between what you should do and what could happen.

  • Corey

    Awesome article, details all the potential pitfalls of implementing IDisposable. I noticed a smallmistake and I wanted to point it out in case someone accidentally incorporates it in their project:SubDisposableClass.Dispose sets _disposed to true before calling the baseclass implementation of Dispose. This will result in the cleanup logic in the base class neverbeing executed (since _disposed will already be set to true).
     

    • http://twitter.com/PhatBoyG Chris Patterson

      DisposableClass and SubDisposableClass both have their own _disposed flag, so it should be fine. Glad you enjoyed the article – be sure to read all the comments as well!

  • Evil Exception

    Swallowing exceptions in the dispose method or finalizer is arguably more dangerous than having the application crash since it can leave your application in an undefined state. I dis-recommend against the advice given in this article. An exception should be an exception and therefore you should do all in your power for preventing Exceptions in the first place and if one is detected, build in the right control flow for preventing that exception from ever happening. Ideally, your application should have no catch blocks.

    • http://twitter.com/PhatBoyG Chris Patterson

      If you are using any third-party library (including most of the .NET runtime, such as WCF and others) there no way you can achieve this “catch-free” system. If there is nothing the calling method can do about the exception (other than explode in a spectacular fashion) – why bother throwing the exception. Sometimes, RPC calls and the like just don’t end in a happy place, and that’s often just fine. Not to mention that so many people call Dispose in a catch block or finally block, without a try/catch around it, which can lead to entire application crashes.

      Which sucks at 2am in a production 24×7 system. Plan for failure, and deal with it in the code so you can sleep at night.

  • fflams

    This is a good article for beginner developpers, however you should check your example.
    When explaining how a derived class should override the Dispose(bool) method, you have it set the _disposed falg to true before calling the base.Dispose, that will result in the base class not doing its dispose job and simply setting object references to null….

    • http://twitter.com/PhatBoyG Chris Patterson

      Both classes have their own private _disposed, so no problem there.

  • RaptorXP

    Hmm yeah, I agree with previous comments. The suggestion in this post is only valid when you want to dispose of unmanaged resources. I can tell you that in 6 years working with .NET, I *NEVER* had to deal with unmanaged resources from .NET.

    It is actually harmful to follow this recommendation if you don’t have unmanaged resources because implementing a finalizer in a class automatically promotes the object to Gen 2, and you’ll end up with poor GC performance.

  • MasaSam

    Good article. Only thing I’ve noticed to other dispose advice articles I have read is that the sample implementation here sets the private _disposed field to true when disposing has done. Some other articles advices to set, and what I usually do, to set the field true right after it is checked in the beginning of protected Dispose method to prevent entering the disposing lines twice.

  • http://twitter.com/Shmuelie Shmueli Englard

    What do you think of http://dave-black.blogspot.com/2011/03/how-do-you-properly-implement.html? I’ve been using it as my template

  • kamranayub

    This is important, and this is a great tip! When I pulled down the latest ActionMailer.Net library from Nuget, I started getting StackOverflowExceptions. Turns out, they didn’t implement IDisposable correctly. I created a pull-request that fixes the issue, but in retrospect, I still missed some tips brought up in this article.

    Thanks for sharing.

  • Peter Son

    Your information about
    CLR is really interesting and innovative. Also I want you to share latest
    updates about this CLR. Can you update it in your website? Thanks for sharing

    Dot
    net training institute in Chennai

  • Dave Black

    It’s unfortunate that you still have not corrected your article to remove the finalizer (or at least make mention of the fact that you should never add a finalizer unless you are needing to release unmanaged resources). I have a pattern I’ve used for many many years and blogged about it here – http://dave-black.blogspot.com/2011/03/how-do-you-properly-implement.html