Disposed objects

There are a few rules about disposed objects. First, calling Dispose on an already disposed object should do nothing. Second, calling any other property or method on an already disposed object should throw an ObjectDisposedException.

Either way, you’ll need a way to determine whether an instance of your disposable class has been disposed. The easiest and most obvious way is to have a simple Boolean member that is set to true when the object is disposed.

More often than not, we find that setting a field to null that wouldn’t otherwise be null works just as well. Commonly, that field needs to be disposed, so we use a utility method that can be used to dispose a field and set it to null - unless it is already null. Using this method ensures that calling Dispose a second time won’t throw a NullReferenceException.

    public static class DisposableUtility
    {
        public static void Dispose<T>(ref T obj) where T : class, IDisposable
        {
            if (obj != null)
            {
                obj.Dispose();
                obj = null;
            }
        }
    }

An easy way to throw ObjectDisposedException when your object has already been disposed is to define a private (or protected) method that throws the exception if necessary; just call that method at the beginning of every property or method definition of your class (besides Dispose, of course).

    sealed class FileReader : IDisposable
    {
        public FileReader(string strFilePath)
        {
            m_stream = new FileStream(strFilePath, FileMode.Open);
        }
        public object ReadNext()
        {
            VerifyNotDisposed();
            object obj = null;
            // ...

            return obj;
        }
        public void Dispose()
        {
            DisposableUtility.Dispose(ref m_stream);
        }
        private void VerifyNotDisposed()
        {
            if (m_stream == null)
                throw new ObjectDisposedException(GetType().Name);
        }
        Stream m_stream;
    }

Nothing too complicated, but it’s easy to forget the two rules of disposed objects. Get in the habit of verifying both rules when you write your unit tests.

Posted by Ed Ball on February 19, 2008