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.