difference between throw and throw new Exception()
The first preserves the original stacktrace:
try { ... }
catch
{
// Do something.
throw;
}
The second allows you to change the type of the exception and/or the message and other data:
try { ... } catch (Exception e)
{
throw new BarException("Something broke!");
}
There's also a third way where you pass an inner exception:
try { ... }
catch (FooException e) {
throw new BarException("foo", e);
}
I'd recommend using:
- the first if you want to do some cleanup in error situation without destroying information or adding information about the error.
- the third if you want to add more information about the error.
- the second if you want to hide information (from untrusted users).
One other point that I didn't see anyone make:
If you don't do anything in your catch {} block, having a try...catch is pointless. I see this all the time:
try
{
//Code here
}
catch
{
throw;
}
Or worse:
try
{
//Code here
}
catch(Exception ex)
{
throw ex;
}
Worst yet:
try
{
//Code here
}
catch(Exception ex)
{
throw new System.Exception(ex.Message);
}
throw;
rethrows the original exception and preserves its original stack trace.
throw ex;
throws the original exception but resets the stack trace, destroying all stack trace information until your catch
block.
NEVER write throw ex;
throw new Exception(ex.Message);
is even worse. It creates a brand new Exception
instance, losing the original stack trace of the exception, as well as its type. (eg, IOException
).
In addition, some exceptions hold additional information (eg, ArgumentException.ParamName
).
throw new Exception(ex.Message);
will destroy this information too.
In certain cases, you may want to wrap all exceptions in a custom exception object, so that you can provide additional information about what the code was doing when the exception was thrown.
To do this, define a new class that inherits Exception
, add all four exception constructors, and optionally an additional constructor that takes an InnerException
as well as additional information, and throw your new exception class, passing ex
as the InnerException
parameter. By passing the original InnerException
, you preserve all of the original exception's properties, including the stack trace.
Throwing a new Exception blows away the current stack trace.
throw;
will retain the original stack trace and is almost always more useful. The exception to that rule is when you want to wrap the Exception in a custom Exception of your own. You should then do:
catch(Exception e)
{
throw new CustomException(customMessage, e);
}