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

}