Monday, November 05, 2007 9:06 PM
This is one of those "Yeah I've always seen people use it differently but I don't know why!" questions. Re-throwing exceptions can be misused, although it may not cause any harm to your application - there are multiple ways of re-throwing an exception, most likely for the purpose of bubbling it up to a higher level. Note to Java developers: It is different in your world.
Lets look at how many ways we can use throw:
- throw
- throw ex
- throw new Exception();
You should not use #3 except if you are throwing a specific exception other that the one that was fired such as a custom exception. To re-throw an exception in .NET your best option is #1 instead of #2 and that is simply because of how they stack up in the stack trace. Lets take a look at the stack trace for both instances using the following snippet.
protected void Page_Load(object sender, EventArgs e)
{
try
{
DoMath();
}
catch(Exception ex)
{
throw ex;
}
}
/// <summary>
/// A method that simply calls another method.
/// </summary>
/// <remarks>
/// Just a helper to show stack trace
/// </remarks>
private void DoMath()
{
MethodWithError();
}
/// <summary>
/// This method will throw an error
/// </summary>
private void MethodWithError()
{
throw new Exception("Generic exception");
}
The stack trace looks like this:
[Exception: Generic exception]
throwerror.Page_Load(Object sender, EventArgs e)
in d:\My Websites\demoweb\throwerror.aspx.cs:22
System.Web.Util.CalliHelper.EventArgFunctionCaller
(IntPtr fp, Object o, Object t, EventArgs e) +15
System.Web.Util.CalliEventHandlerDelegateProxy.Callback
(Object sender, EventArgs e) +34
System.Web.UI.Control.OnLoad(EventArgs e) +99
System.Web.UI.Control.LoadRecursive() +47
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint,
Boolean includeStagesAfterAsyncPoint) +1061
However, if I replace "throw ex;" with just "throw;", here is the new stack trace.
[Exception: Generic exception]
throwerror.MethodWithError() in d:\My Websites\demoweb\throwerror.aspx.cs:42
throwerror.DoMath() in d:\My Websites\demoweb\throwerror.aspx.cs:34
throwerror.Page_Load(Object sender, EventArgs e) in d:\My Websites\demoweb\throwerror.aspx.cs:22
System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e) +15
System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +34
System.Web.UI.Control.OnLoad(EventArgs e) +99
System.Web.UI.Control.LoadRecursive() +47
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1061
Its all about the details. Obviously, using just "throw;" gives us much more details - so use "throw" to re-throw an error.