Reputation: 19074
I've got it in my head that throwing an exception has side effects (like collecting stack information), but I'm realizing it might not. Is there a difference between the following two versions of GetException
?
public Exception GetException() {
try {
throw new Exception("Bummer");
}
catch (Exception e) {
return e;
}
}
public Exception GetException() {
return new Exception("Bummer");
}
Upvotes: 2
Views: 286
Reputation: 111920
When an exception is thrown, the stack trace is "inserted" into the exception (that is what you can get through the StackTrace
property). So yes, there is a side-effect in throwing an exception object.
A problem of rethrowing an exception (even with
throw;
is that the stack trace is mangled (or even overwritten, if you use throw ex;
))
Note that throw;
is better than throw ex;
, because the first one will only mangle a little the line numbers, while the later will reset totally the stack trace.
There are some persons that don't trust... Look at https://dotnetfiddle.net/RXicN9 and check the line numbers. They are different.
a more complete example that shows that only the method with the two try... catch...
has its line numbers mangled: https://dotnetfiddle.net/jJyYWB
See Incorrect stacktrace by rethrow for an explanation. Note that this is a special case, that happens only if an exception is thrown twice in the same method.
Upvotes: 3
Reputation: 63772
Yes, the two are different. The throw
will modify the stack trace information in the Exception
object - so your second example will still produce an exception, but without the stack trace information.
Exception
-derived classes are classes as any other - all the "magic" happens with the throw
keyword.
This is also the reason why it's a bad idea to rethrow the exception by doing throw ex;
- you either want to use throw;
(although careful about the issue of rethrowing in the same method that Xanatos pointed out), or you want to wrap the inner exception (ie. throw new MyException(ex)
). In both cases, there's still some minor changes that can complicate debugging, but if you're well prepared, it helps a lot.
This behaviour is actually quite useful. For one, it means that you can have helper methods that construct exceptions for you to throw (this is used all over the place in .NET code itself). Two, it allows the runtime to actually throw exceptions like StackOverflowException
and OutOfMemoryException
- both have their instances created when the application starts, and when the issue occurs, they only throw - a new
would fail, of course.
Upvotes: 2