SYSK 212: Does .NET Garbage Collector call Dispose? Dispose – Best Practices.


Since there are still developers out there that are not clear on if/when should you call Dispose, and what your class’s finalizer should look like if it holds on to non-memory resources such as file handles, GDI objects, database connections, etc., I decided to write this post on Dispose best practices.


 


The first question is – does .NET garbage collector call Dispose for me when destroying the object?  The answer is – NO!  The good news is that all Microsoft framework classes that implement IDisposable pattern also call Dispose from the class destructor, of course, first checking if resources have already been released.  You should too!  IDisposable pattern was created so that users of a class holding non-memory resources tell that class when it’s time to release those resources instead of waiting for the garbage collector’s algorithm to kick in.  This prevents situations of running out of limited resources (e.g. database connections) on system with high available memory. 


 


Best practice:  always call Dispose on a class that implements it when you are done with it.  In C#, you can use the ‘using’ statement to do that for you transparently.  And remember to handle exceptions – code in such a way that you call Dispose regardless of whether your method throws or catches an exception.


 


Best practice:  When implementing a class that holds on to non-memory resources beyond the method scope, always implement IDisposable interface.  IMPORTANT: in you class’s destructor, check whether the Dispose method was called by the user of your class, and, if not, call it yourself.  Consider throwing an exception (in debug only builds) in cases when your destructor was reached and the Dispose was not called.


 


Summary:  here is the pattern I use:


      // Thanks Niall, Simon, Anders, Denis, russel, hasanib and James for the comments!  Right on!


public class X : IDisposable


{


    private bool _disposed = false;


 


    // Some non-memory resource declared here


    // and initialized somewhere in this class


    public X()


    {


      


    }


 


    ~X()


    {


#if __DEBUG


        if (false == _disposed)


            throw new ApplicationException("X.Dispose() was not called!"); 


#endif


        if (false == _disposed)


            Dispose(false);


    }


 


    #region IDisposable Members


 


    public void Dispose()    


    {


        Dispose(true);       


 


        GC.SuppressFinalize(this);


    }


 


    // If disposing equals false, the method has been called by the 
    // runtime from inside the finalizer and you should not reference 
    // other objects. Only unmanaged resources can be disposed.


    private void Dispose(bool disposing)    


    {


        if (!_disposed)


        {


            // TODO: your code here to release resources


           _disposed = true;         


        }


    }


 


 


    #endregion


}


 

Comments (9)

  1. Niall says:

    You should use GC.SuppressFinalize, otherwise you are adding to collection time and GC workload for every type you use this pattern on, due to adding the finalizer.

  2. Simon says:

    I suggest you declare your Dispose method as virtual, to allow child classes to override it. In child classes, think to call the base implementation (to set the _disposed flag to true).

    Another good implementation of IDisposable is the System.ComponentModel.Component one.

  3. Anders Dalvander says:

    I do something like this.

    public class DisposableClass : IDisposable, DisposableBaseClass
    {
    ~DisposableClass()
    {
    Dispose(false);
    }

    private bool disposed = false;

    protected virtual /*or override*/ void Dispose(bool disposing)
    {
    try
    {
    if (!this.disposed)
    {
    if (disposing)
    {
    // Clean up managed resources.
    }

    // Clean up unmanaged resources.
    }

    this.disposed = true;
    }
    finally
    {
    base.dispose(disposing);
    }
    }

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

  4. Denis says:

    Better to do this:

    #if __DEBUG

    ~X()

    {
    if (false == _disposed)
    throw new ApplicationException(“X.Dispose() was not called!”);

    }
    #endif

  5. russel says:

    Implenting a destructor in C# just put the class in Finalize queue, it is the GC call Dispose() if the user does not call the dispose. we just do not know we it will be called which results long holding of precious resource.

  6. hasanib says:

    Great post!!!

    Why don’t you use the “I have a protected virtual Dispose method that takes a boolean indicating whether I’m being called from within the finalizer or user code, and I’ll have a public non-virtual method that calls Dispose(true) followed by a call to GC.SuppressFinalize” pattern?

  7. IMHO, this may have been better off as a link to the FDL page @ http://msdn2.microsoft.com/en-us/library/b1yfkh5e.aspx

    Specific issues:
    – Dispose(bool) pattern
    – suppressing finalization if Dispose() was called
    – calling out how finalization-time dispose is different (can’t cross managed references like you can with a normal dispose)

    Also, if the non-memory resource happens to exist via a handle, then promoting the use of SafeHandle subclasses (either one of the existing ones or creation of a new one) is a huge help, as it pushes down the problem to an isolated type, helping everything from code complexity to the size of the object graph that is necessarily promoted to Gen 1 due to being in the finalization queue.

    Anyway, IMHO 🙂

  8. Kris says:

    When I do this, I also add a System.Diagnostics.StackTrace member variable which I create in the constructor (all of it wrapped in #if __DEBUG’s. Doing this is very useful because when you get your exception you can look at the StackTrace member to see the exact line of code that constructed the object.

Skip to main content