What are the best practices to consider when catching exceptions and re-throwing them? I want to make sure that the Exception
object's InnerException
and stack trace are preserved. Is there a difference between the following code blocks in the way they handle this?
try
{
//some code
}
catch (Exception ex)
{
throw ex;
}
Vs:
try
{
//some code
}
catch
{
throw;
}
If you throw a new exception with the initial exception you will preserve the initial stack trace too..
Nobody has explained the difference between
ExceptionDispatchInfo.Capture( ex ).Throw()
and a plainthrow
, so here it is. However, some people have noticed the problem withthrow
.The complete way to rethrow a caught exception is to use
ExceptionDispatchInfo.Capture( ex ).Throw()
(only available from .Net 4.5).Below there are the cases necessary to test this:
1.
2.
3.
4.
Case 1 and case 2 will give you a stack trace where the source code line number for the
CallingMethod
method is the line number of thethrow new Exception( "TEST" )
line.However, case 3 will give you a stack trace where the source code line number for the
CallingMethod
method is the line number of thethrow
call. This means that if thethrow new Exception( "TEST" )
line is surrounded by other operations, you have no idea at which line number the exception was actually thrown.Case 4 is similar with case 2 because the line number of the original exception is preserved, but is not a real rethrow because it changes the type of the original exception.
When you
throw ex
, you're essentially throwing a new exception, and will miss out on the original stack trace information.throw
is the preferred method.I would definitely use:
That will preserve your stack.
FYI I just tested this and the stack trace reported by 'throw;' is not an entirely correct stack trace. Example:
The stack trace points to the origin of the exception correctly (reported line number) but the line number reported for foo() is the line of the throw; statement, hence you cannot tell which of the calls to bar() caused the exception.
A few people actually missed a very important point - 'throw' and 'throw ex' may do the same thing but they don't give you a crucial piece of imformation which is the line where the exception happened.
Consider the following code:
When you do either a 'throw' or 'throw ex' you get the stack trace but the line# is going to be #22 so you can't figure out which line exactly was throwing the exception (unless you have only 1 or few lines of code in the try block). To get the expected line #17 in your exception you'll have to throw a new exception with the original exception stack trace.