How to handle exception thrown from Dispose?

Morgan Cheng picture Morgan Cheng · Jun 23, 2009 · Viewed 21.1k times · Source

Recently, I was researching some tricky bugs about object not disposed.

I found some pattern in code. It is reported that some m_foo is not disposed, while it seems all instances of SomeClass has been disposed.

public class SomeClass: IDisposable
{
    void Dispose()
    {
       if (m_foo != null)
       {
          m_foo.Dispose();
       }
       if (m_bar != null)
       {
          m_bar.Dispose();
       }   
    }

    private Foo m_foo;

    private Bar m_bar;

}

I suspects that Foo.Dispose might throw a exception, so that following code is not executed so m_bar is not disposed.

Since Foo/Bar might be from third party, so it is not guaranteed to not throwing exception.

If just wrap all Dispose invocation with try-catch, the code will turn to be clumsy.

What's best practice to handle this?

Answer

Sam Saffron picture Sam Saffron · Jun 23, 2009

Its true that it can be pretty bad to leak out an exception of your dispose method, especially since stuff that implements IDisposable will usually specify a finalizer that will call Dispose.

The problem is that sweeping the problem under of the carpet by handling an exception may leave you with some very hard-to-debug situations. What if your IDisposable allocated a critical section of sorts that only gets released after dispose. If you ignore the fact that the exception happened, you may end up in deadlock central. I think failures in Dispose should be one of those cases where you want to fail early, so you can fix the bug as soon as its discovered.

Of course it all depends on the object being disposed, for some objects you may be able to recover, others not. As a general rule of thumb, Dispose should not throw exceptions when used correctly and you should not have to code defensively around exceptions in nested Dispose methods you are calling.

Do you really do not want to sweep an OutOfMemoryException under the carpet?

If I had a dodgy 3rd party component that arbitrarily threw exceptions on Dispose I would get it fixed AND host it in a separate process that I could tear down when it started playing up.