C# Using Blocks can Swallow Exceptions | DigitallyCreated
Posted by jpluimers on 2011/09/22
I got to the SafeUsingBlock extension method because of a nice StackOverflow thread on exceptions swallowed in a using block.
Actually, you can broaden the case into a wider scope: in any language when you protect resources in a try finally block (essentially, a using will turn into an implicit try finally block), and both the core logic and the finally throw an exception, the exception from the core block is swallowed.
Simple C# example:
using System;
public class Example
{
public void Main()
{
try
{
try
{
throw new ApplicationException("logic block");
}
finally
{
throw new ApplicationException("finally block");
}
}
catch (Exception error)
{
Console.WriteLine(error.ToString());
}
}
}
Simple Delphi example:
program Example;
begin
try
try
raise Exception.Create('logic block');
finally
raise Exception.Create('finally block');
end;
except
on error: Exception do
begin
Write(error.ClassName, ' ', error.Message);
end;
end;
end.
Both examples will only write out the finally block exception message, not the logic block exception message.
This is a corner case (like the example from the MSDN documentation), from which the SafeUsingBlock protects you from by providing an AggregateException class.
In C#, it is a guideline to avoid throwing exceptions in the Dispose when implementing the disposable pattern.
This is good practice in any programming environment: when disposing objects, only throw exceptions in very critical situations when the containing process has been corrupted.
Practically this is very easy as the disposers are very thin and should not contain any business logic, so it is pretty easy to spot places where the program state really is corrupt.
An other alternative is for instance have a Close method that throws an exception, and a disposer not throwing.
–jeroen
via C# Using Blocks can Swallow Exceptions | DigitallyCreated.






Jolyon Smith said
Isn’t this a case of worrying about the wrong problem?
If your “finally” is so complex that it might raise a _legitimate_ exception of concern then you should be paying more attention to your exception handling in that case anyway. Almost by definition your code goes beyond the expected usage pattern for try..finally.
Most “finally” blocks are so simple (free’ing previously created objects, closing handles etc) that if you get an exception in that block then whatever the problem is likely to be far more important than any other exception that might have been raised in the “logic” block. So whilst hiding it may be a technical nuisance, knowing about it doesn’t actually help you very much either.
And again, if the fact that the original exception has become “hidden” by the later exception then the real problem is the way you are handling your exceptions, not the (defined and documented) behaviour of the tools at your disposal for implementing that handling.
imho. ymmv. :)
jpluimers said
The main reason I posted this is that a while ago, a finally go would raise an exception caused by the try block malforming the resource and (correctly!) throwing an exception when it detected it had. Because I was so focused on the wrong exception (the exception from the try block was hidden by the one from the finally block), it took me a while to find the actual cause.
I forgot the exact solution, but it came down to the opposite of your conclusion: in my case the try block was too complex.
As with many of my blog posts: they are just write downs of things I should remember from the past, but probably won’t :)
Jolyon Smith said
Yes, sorry it wasn’t perhaps clear that my “worrying about the wrong problem” observation was directed more at the comments that were seemed to be intent on finding a mechanism for preserving nested exceptions than at the original post.
:)
Alex said
“throw new” – that’s a weird Delphi syntax ;)
Anyway, you can do
try
try
Exception.RaiseOuterException(Exception.Create(‘logic block’));
finally
Exception.RaiseOuterException(Exception.Create(‘finally block’));
end;
except
on error: Exception do
begin
Write(error.ClassName, ‘ ‘, error.ToString);
end;
end;
Or you can setup RTL to auto-capture nested exceptions.
Martijn Coppoolse (@vor0nwe) said
Auto-capturing nested exceptions? Is that like automatically doing Exception.RaiseOuterException when there’s already an exception? And how do you setup the RTL to do that?
jpluimers said
Fixed type typo.
Note that RaiseOuterException was only introduced in Delphi 2009 (http://www.marcocantu.com/code/dh2009/ExceptionsTest.htm) and documented in Delphi 2010: http://docwiki.embarcadero.com/VCL/2010/en/SysUtils.Exception.RaiseOuterException
I’m not sure this is the correct way to raise exceptions in the two sections of the try/finally block though.
–jeroen
Danny Thorpe (@danny_thorpe) said
You can go broader still: Any time a new exception is thrown, it will obliterate any previous exception in progress. This applies to finally blocks as well as catch blocks. The “current exception” also exists in a catch block, since it can be rethrown with the statement “throw;” The “current exception” is a global variable within a thread (thread local variable). Only one exception at a time can sit in a thread’s current exception slot.