Throwing Exceptions and Keeping the Stack Trace
Since its beginning, C# offered two ways to rethrow an exception in a catch block:
- With the caught exception as a parameter to throw; (e.g.: throw ex);
- Without any explicit parameter, in which case, it would be assumed to be the currently caught exception (e.g.: throw).
What was the difference? Well, if you were to throw an exception explicitly, its stack trace would be cleared, and replaced by a new one, starting on the current method; on the other hand, the parameterless throw clause would keep the stack trace, which is what we normally want. That is why the recommendation is to use the parameterless throw version:
void MyMethod(){ try { //do something that possibly throws an exception}
catch (Exception ex) {DoSomethingWithThis(ex);
throw;}
}
void DoSomethingWithThis(Exception ex){ //do something with ex}
As of .NET 4.5, there is another way to rethrow an exception that still keeps its stack trace, provided by the ExceptionDispatchInfo.Capture method:
void MyMethod(){ try { //do something that possibly throws an exception}
catch (Exception ex) {DoSomethingWithThis(ex);
}
}
void DoSomethingWithThis(Exception ex){ //do something with ex var capture = ExceptionDispatchInfo.Capture(ex); //works even if ex is nullif (capture != null)
{ capture.Throw(); //call stack from MyMethod will be kept}
}
Not a substantial difference, but this gives us more control, which is usually good! ![]()