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.

Comments (9)

RyanOctober 31st, 2002 at 12:42 pm

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.

LanikFebruary 11th, 2003 at 1:48 pm

Actually, this *does* work.

rsponaugleMarch 9th, 2003 at 4:40 pm

Lanik, tomasr: Works *very* well… :)

csOctober 31st, 2003 at 4:45 pm

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;
}
}

RjMarch 30th, 2007 at 1:41 pm

Didn’t work for me.

software developerAugust 11th, 2009 at 9:59 am

Cool,

But I thisnk it is better to write error message and detail te be able to under stand the error better

Thanks for writing

JoeAugust 22nd, 2009 at 1:13 am

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.

SaboteurDecember 3rd, 2009 at 12:31 pm

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

XanderJanuary 12th, 2010 at 3:57 pm

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 comment

Your comment