Rethrowing Exceptions in C#

I've been somewhat surprised by this topic in the past few weeks, since it is one that has comed up in a number of circles. Basically, the comments I've heard have related to the lose of stack trace information when "rethrowing" an exception from withing a catch clause in C#.

But then, when I go look at the code, I see people have been doing something like this:

} catch ( Exception e ) {
   // do something here with e, then rethrow
   throw e;
}

So, no wonder people have been missing stack trace information! In the code above, you're not rethrowing e, just merely beginning a new exception flow using the same exception object instance. It's worthwhile to remember that the C# throw syntax is throw expr, where expr is an expression that evaluates to an exception object. It doesn't need to be a new object, any Exception-derived object will do, even if it was created half an hour ago and has been thrown 7 times before.

But what really left me consternated was seeing other people offer the following suggestion to "fix" this issue:

} catch ( Exception e ) {
   // do something here with e, then rethrow
   throw new Exception("",e);
}

So now, you have complete stack trace information, but only by combining the information in both the outer and inner exception objects. How is that a fix for this? It's a hack, and a poor one, at that.

It turns out, though, that C# has provided a very simple syntax to provide the needed rethrowing semantics all along [1], but it seems not very people know about it. This left me puzzled, since it's essentially the same syntax used by C++ [2]: an empty throw statement. So, our example, correctly done, would be:

} catch ( Exception e ) {
   // do something here with e, then rethrow
   throw;
}

Simple, isn't it?

[1] See Section 8.9.5 of the C# language specification.
[2] This is defined in section 15.1 para 6 of the ISO 14882 C++ spec.

15 comments

  1. But the problem is that if you actually tried this you’d find it didn’t work. Try it out sometime and you will see that the code you use above will lose the stack trace information. At least this is true with Visual Studio .NET and the .NET framework SP2. If it’s working for you maybe you could explain.

  2. I agree with Ryan. It does not work. The stack trace will point to the first throw, not where the error was generated.

    Try the following:

    ///
    /// The main entry point for the application.
    ///
    [STAThread]
    static void Main(string[] args)
    {
    try
    {
    Function1();
    }
    catch (Exception ex)
    {
    Console.WriteLine (ex.ToString ());
    }

    Console.ReadLine ();
    }

    static void Function1 ()
    {
    try
    {
    Function2 ();
    }
    catch (Exception)
    {
    throw;
    }
    }

    static void Function2 ()
    {
    try
    {
    Function3 ();
    }
    catch (Exception)
    {
    throw;
    }
    }

    static void Function3 ()
    {
    int i = 0;
    int j = 0;

    try
    {
    Console.WriteLine ((i/j).ToString ());
    }
    catch (Exception)
    {
    throw;
    }
    }

  3. Thanks.

    You say a lot of people get this wrong… for me, it is because I am coming from Java.

    In Java, rethrowing an exception with “throw e;” will keep the original stack trace. The stack information is added to the exception object only the first time it is thrown.

  4. Microsoft sucks.
    More complicated solution to Exception handling and you can still sometimes loose stack :(

  5. To “CS” : Actually it did work for me in VS2005, that very code sample you posted reported the exception was thrown in Function3()… below is the stack trace from your example

    StackTrace ” at RethrowExceptionTester.Program.Function3() in Program.cs:line 62\r\n at RethrowExceptionTester.Program.Function2() in Program.cs:line 47\r\n at RethrowExceptionTester.Program.Function1() in Program.cs:line 35\r\n at RethrowExceptionTester.Program.Main(String[] args) in Program.cs:line 17″

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>