In C#, throw ex
is almost always wrong, as it resets the stack trace.
I just wonder, is there any real world use for this? The only reason I can think of is to hide internals of your closed library, but that's a really weak reason. Apart from that, I've never encountered in the real world.
Edit: I do mean throw ex
, as in throwing the exact same exception that was caught but with an empty stacktrace, as in doing it exactly wrong. I know that throw ex has to exist as a language construct to allow throwing a different exception (throw new DifferentException("ex as innerException", ex)
) and was just wondering if there is ever a situration where a throw ex
is not wrong.
Unlike throw ex, throw provides all stack information. The main difference between throw and throw ex in C# is that throw provides information about from where the exception was thrown and also about the actual exception while throw ex provides information only about from where the exception was thrown.
It is good programming practice to avoid this usage where possible. If null is a reasonable value for the stated purpose of a method, or if a method is expected to fail often in the normal course of operation, then it is reasonable to return null to indicate failure; otherwise it is better to throw an exception.
Exceptions should only be used in exceptional circumstances and therefore should be used sparingly. For example, it is correct to use an exception when you are attempting to access the Twitter API and do some processing because if this fails it is an exceptional circumstance.
I have never seen it used on purpose, but that of course doesn't mean anything.
Let's look at the alternatives:
catch(Exception ex)
{
// do stuff (logging)
throw; // a) continue ex
throw new SomeException("blah", ex); // b) wrap
throw new SomeException("blah"); // c) replace
throw ex; // d) reset stack-trace
}
Both c) and d) are dropping the stack-trace, the only 'advantage' of d) that I can see is that throw ex;
preserves the exact type and possible extra properties (SQL error) of ex
.
So is there ever a case where you want to keep all information of an exception except the stack-trace? Not normally, but some speculation:
If you stop to think about it, throw ex
is actually used pretty frequently - except with an unnamed local variable. It would be pretty difficult to (re-)design the language so that:
throw new ArgumentException();
was valid, but
var ex = new ArgumentException();
throw ex;
was invalid (and then extend this for tracing more complex variable assignments). I.e. throw ex
is the "normal" form of the throw statement, but it is usually wrong when re-throwing an already caught exception.
There is no valid reason to re-throw exception objects i.e. 'throw ex'.
It's a language\compiler feature that's possible although doesn't add any value in practice over the negative effect it has. This is a similar situation to being able to write code to access members on null references - it's of course possible but has no value, e.g.:
//Possible but not useful.
object ref1 = null;
ref1.ToString();
Being able to re-throw exception objects is unfortunate and very often misunderstood by rookies and experienced coders alike, that is until you get an unhandled exception in production with a truncated stack trace logged.
There is the tenuous feeling that it could be used to intentionally hide stack trace information, but throwing a new exception would be the correct way to do this.
I would go as far as to say that being able to re-throw exception objects (i.e. 'throw ex') is a design flaw - it's just too easy to do the wrong thing. However, I suspect that this is a design trade-off in the compiler for performance reasons as it would incur an overhead to validate that 'throw ex' was not a 're-throw'. I'm sure there are many such trade-offs.
throw ex
is just an error or a typo made by people who don't know or forget about throw;
.
It can be intended probably in one case only, pointed by other people in their answers: the situation where you don't want the proper stack trace to be sent to the caller, but you still want to keep the type of the exception previously thrown. In practice, I can hardly imagine the case when somebody will need it, and will not use throw new SomeCustomException(...)
instead.
FxCop rule CA2200 RethrowToPreserveStackDetails
goes in the same way, inviting you to rethrow an exception correctly by using throw;
:
try
{
// ...
}
catch (SomeException ex)
{
Logger.AddException(ex);
throw;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With