This was a telephone interview question I had: Is there a time when Dispose will not be called on an object who's scope is declared by a using block?
My answer was no - even if an exception happens during the using block, Dispose will still be called.
The interviewer disagreed and said if using
is wrapped in a try
-catch
block then Dispose will not be called by the time you enter the catch block.
This goes contrary to my understanding of the construct, and I haven't been able to find anything that backs up the interviewers point of view. Is he correct or might I have misunderstood the question?
The other answers about power failure,
Environment.FailFast()
, iterators or cheating byusing
something that isnull
are all interesting. But I find it curious that nobody mentioned what I think is the most common situation whenDispose()
won't be called even in the presence ofusing
: when the expression insideusing
throws an exception.Of course, this is logical: the expression in
using
threw an exception, so the assignment didn't take place and there is nothing we could callDispose()
on. But the disposable object can already exist, although it can be in half initialized state. And even in this state it can already hold some unmanaged resources. This is another reason why correctly implementing the disposable pattern is important.Example of the problematic code:
Here, it looks like
Foo
releasesm_resource
correctly and we are usingusing
correctly too. But theDispose()
onFoo
is never called, because of the exception. The fix in this case is to use finalizer and release the resource there too.The interviewer is partially right.
Dispose
may not correctly clean up the underlying object on a case-by-case basis.WCF for example has a few known issues if an exception is thrown while in a using block. Your interviewer was probably thinking of this.
Here is an article from MSDN on how to avoid issues with the using block with WCF. Here is Microsoft's official workaround, although I now think that a combination of that answer and this one is the most elegant approach.