Friday, October 08, 2010

IDisposable and Finalizers

Finalizers are NOT required if you do not keep references to unmanaged resources in your class. I repeat, you do not need a Finalizer, if your class does not use unmanaged objects.

According to MSDN, the pattern for using IDisposable with a Finalizer is:

        // Implement IDisposable. Do not make this method virtual.
        // A derived class should not be able to override this method.
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        // Dispose(bool disposing) executes in two distinct scenarios.
        // If disposing equals true, the method has been called directly
        // or indirectly by a user's code. Managed and unmanaged resources
        // can be disposed.
        // 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)
        {
            // Check to see if Dispose has already been called.
            if(!this.disposed)
            {
                // If disposing equals true, dispose all managed
                // and unmanaged resources.
                if(disposing)
                {
                    // Dispose managed resources.
                    component.Dispose();
                }

                // Call the appropriate methods to clean up
                // unmanaged resources here.
                // If disposing is false,
                // only the following code is executed.
                ………
                // Note disposing has been done.
                disposed = true;

            }
        }

        // Use C# destructor syntax for finalization code.
        // This destructor will run only if the Dispose method
        // does not get called.
        // It gives your base class the opportunity to finalize.
        // Do not provide destructors in types derived from this class.
        ~MyResource()
        {
            // Do not re-create Dispose clean-up code here.
            // Calling Dispose(false) is optimal in terms of
            // readability and maintainability.
            Dispose(false);
        }

The reason we have the following block of code in Dispose(bool disposing):

if(disposing)
{
}

is that, if Dispose was called by the destructor, then the GC is cleaning up managed memory and you cannot reference any managed objects during or at any point in time after that.

Now, based on the above general disposable pattern implementation, if your class does not have any unmanaged resources and Dispose has not been called by the user, then Dispose will be called by the runtime with a value of false (Dispose(false)). This would mean that “Dispose(bool disposing)” will do nothing at all. If dispose wont do anything at all, why does this matter? Because, when you implement a finalizer, your object will never get cleaned up in GC gen 0 and it will always move up to GC gen 1 and hence you get a performance hit – object has to stay around for much longer than it needed to.

If you look at the MSDN documentation, you will see that it states that “the dispose pattern is used only for objects that access unmanaged resources”, so you would TYPICALLY create a finalizer for your class. Why typically? Because you may want to provide the ability for developers to use your class in a using block. The using block is allowed only on those classes that implement IDisposable (link). So in this case, you would implement Dispose and put all your code in the dispose method and not create a finalizer or the protected “Dispose(bool disposing)” methods. (note: in this case you do not need to call GC.SuppressFinalize(this))

No comments: