Search code examples
c#idisposableobjectdisposedexception

Disposing objects exception


While crawling through sources on the web, I've encountered a lot of boiletplate code which looks the following way:

Suppose we have some public class CustomObject: IDisposable, which has a bunch of methods.

Now, each of those methods has default sanity checks:

if (inputBuffer == null)
    throw new ArgumentNullException("inputBuffer");
if (outputBuffer == null)
    throw new ArgumentNullException("outputBuffer");
if (inputCount < 0)
    throw new ArgumentException("inputCount", "< 0");

But (due to the IDisposable interface implementation) the following check is added to each method:

if (disposed)
    throw new ObjectDisposedException("MethodName");

Now - is this a common practice? Should I start reengineering my old disposable classes and implementing these checks?


Solution

  • It depends upon your usage, if in doubt it doesn't hurt to add it.

    For a class intended to be used by other programs (e.g., libraries and frameworks) I would always perform this check and throw the correct exception as this will aid other applications in diagnosing errors and makes the class more robust.

    For internal classes only intended to be consumed by my application you can skip the check if the error will surface quickly when calling the methods. E.g. if every method in the class used a stream, and that stream was disposed or set to null it would result in an exception pretty quickly.

    If the internal class has methods that won't error though, I will always use an explicit check as I don't want a situation where some of the methods still work after the object has been disposed (except for methods that explicitly allow it such as IsDisposed).

    Having the explicit check does have the advantage of explicitly documenting which methods are allowed to be called after the object has been disposed. More so if you add a comment at the top of methods that do not call GuardDisposed to state that it is allowed, then any method that doesn't start with GuardDisposed or a comment can be regarded as suspect.

    To actually implement the check I prefer to move it to a separate method and use it like an assertion, e.g.

    public class Foo
    {
        private bool disposed;
    
        public void DoSomething ()
        {
            GuardDisposed ();
        }
    
        protected void GuardDisposed ()
        {
            if (disposed)
                throw new ObjectDisposedException (GetType ().Name);
        }
    }