The Wiert Corner – irregular stream of stuff

Jeroen W. Pluimers on .NET, C#, Delphi, databases, and personal interests

  • My badges

  • Twitter Updates

  • My Flickr Stream

  • Pages

  • All categories

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 2,805 other followers

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.

7 Responses to “C# Using Blocks can Swallow Exceptions | DigitallyCreated”

  1. 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 :)

      • 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.

        :)

  2. 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.

  3. 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.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

 
%d bloggers like this: