Rethrowing Exceptions in C#

Link. September 14, 2002. Comments [5]. Posted in: .NET
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.



Thursday, October 31, 2002 2:42:37 PM (SA Pacific Standard Time, UTC-05:00)

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.

Ryan
Tuesday, February 11, 2003 4:48:32 PM (SA Pacific Standard Time, UTC-05:00)

Actually, this *does* work.

Lanik
Sunday, March 09, 2003 6:40:20 PM (SA Pacific Standard Time, UTC-05:00)

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

rsponaugle
Friday, October 31, 2003 6:45:00 PM (SA Pacific Standard Time, UTC-05:00)

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;

}

}

cs
Friday, March 30, 2007 3:41:46 PM (SA Pacific Standard Time, UTC-05:00)
Didn't work for me.
Rj
Comments are closed.

About

Tomas Restrepo is co-founder of devdeo. His interests include .NET, Connected Systems, PowerShell and, lately, dynamic programming languages. More...

email: tomas@winterdom.com
msn: tomasr@passport.com
twitter: tomas_restrepo

Technorati Profile

devdeo logo

View my profile on LinkedIn

MVP logo

Syndicate

Ads


Links

Categories

Statistics

Total Posts: 1006
This Year: 76
This Month: 7
This Week: 0
Comments: 771

Blogroll

Post Archive

Other

Copyright © 2002-2008, Tomas Restrepo.

Powered by: newtelligence dasBlog 1.9.7174.0

Sign In