I received a question about Item 15 in the second edition of Effective C#. I thought the question and answer would be of general interest, so I’m addressing it here. The question:
You stated in your book (Kindle page number 1359) that if you stack the using statements of IDisposable objects that it could have a potential resource leak if an exception is thrown. I however, have been unable to see this happen, I even wrote my own example to see if this is the case. Please can you elaborate on this particular scenario?
Here’s the sample he sent along:
class Program
{
static void Main(string[] args)
{
try
{
TestObject outer = new TestObject("outer");
TestObject inner = new TestObject("inner");
using (outer as IDisposable)
using (inner as IDisposable)
{
throw new NotImplementedException();
}
}
finally
{
Console.ReadLine();
}
}
class TestObject : IDisposable
{
public TestObject(string name)
{
Name = name;
}
public string Name { get; set; }
authors note: The rest of this blog post reads much better if you imagine it read by Henry Fonda as Juror #8 in 12 Angry Men.
The code, as written, does call Dispose() on both TestObjects created. If that’s what happened, multiple using statements like this work just fine.
But, suppose that’s not what happened. Suppose, just suppose, the constructor for TestObject throws an exception when creating the second TestObject.
In that case, the outer TestObject has been created, but neither using statement is reached. Dispose will not be called on the outer TestObject. Resources would leak. Maybe that’s what could happen. Just maybe. We should think about this more.
Maybe the constructor doesn’t throw an exception. Most developers do try to write constructors that minimize the chance of a constructor exiting by throwing an exception. Maybe that won’t happen. Maybe it’s safe as is.
Read more: Bill Wagner