binard
binard

Reputation: 1784

Why does the C# compiler authorize "throw ex" in catch, and is there a case where "throw ex" is useful?

In C#, younger developers use often "throw ex" instead of "throw" to throw exception to parent method.

Example :

try
{
    // do stuff that can fail
}
catch (Exception ex)
{
    // do stuff
    throw ex;
}

"throw ex" is a bad practise because the stack trace is truncated below the method that failed. So it's more difficult to debug code. So the code must be :

try
{
    // do stuff that can fail
}
catch (Exception ex)
{
    // do stuff
    throw;
}

My question is why compilator authorize this (or doesn't display a warning message ?) Is there a case which "throw ex" is useful ?

Upvotes: 6

Views: 320

Answers (4)

user645280
user645280

Reputation:

I guess I consider catch the culprit when you actually just want something to propagate up the stack. Shouldn't catch be avoided entirely in favor of finally?

bool bSucceeded = false;
try
{
    // do stuff that can fail
    bSucceeded = true;
}
finally
{
    if( !bSucceeded ) 
        // do stuff you need to do only on error.  (rare, for me)

    // cleanup stuff (you're nearly always doing this anyways right?)
}

I've written many bSucceded's, and don't think I have ever written throw inside catch without wrapping in a new Exception(). (At least since I was first learning Java in '99 or so.)

I'm guessing the massive number of possible ways to deal with this is why they let you do what you want here instead of trying to lock it down.

Upvotes: 0

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726469

While compilers can certainly prevent some obvious programming errors, they cannot possibly watch out for best practices like that without triggering some inevitable false positives along the way.

Programmers could choose to change the content of the exception inside the exception handler, or throw a brand-new exception instead. In both cases a message that warns about throwing an exception from an exception handler would be annoying and useless.

One case when it make sense to change the internal state of an exception happens when you throw an exception from a recursive function. Consider a recursive descent parser reporting an error from several layers down the recursive chain. Each level of invocation could potentially add more useful information to an exception. However, wrapping exceptions of each subsequent layer into a new exception is not practical in this case, because you end up with a recursive data structure representing a flat list. One viable solution for situations like this would be creating a custom exception to which each catcher can add more details before re-throwing it. Since the function (or more precisely, a group of functions) is recursive, the location in code from which the original exception has been thrown is of less importance than the completeness of the context that lead to the exception in the first place.

It does not mean that finding situations like that is entirely useless: code proofing tools, such as ReSharper, can certainly help programmers watch out for issues like this. The compiler, however, is a poor choice for a best practice watchdog, because for the most part the compiler should do what it is told.

Upvotes: 1

Habib
Habib

Reputation: 223212

throw new Exception(); or throw ex; both will use the same language rules to allow throwing an exception object, (whether new or existing). When you want to add some extra information with the exception than that option is helpful.

See: How to: Explicitly Throw Exceptions - MSDN

You can explicitly throw an exception using the throw statement. You can also throw a caught exception again using the throw statement. It is good coding practice to add information to an exception that is re-thrown to provide more information when debugging.

Since both, throw new Exception() and throw ex; would require the same language rules, it is not really compiler's job to distinguish those two.

Simply throwing the existing exception without any modification to the exception object would be using the same language construct.

Also as @D Stanley has pointed out in his answer, that truncating the stack trace could be the desired behaviour.

As far as your question about compiler not warning about it is concerned, It is not the job of compiler to warn about bad practices, there are code analysis tools. For example Managed Code Analysis tool will raise the warning for throw ex; CA2200: Rethrow to preserve stack details

Upvotes: 4

D Stanley
D Stanley

Reputation: 152491

Is there a case which "throw ex" is useful ?

Sure - sometimes you want to truncate the stack trace - to avoid exposing implementation details, etc. Other times you may want to throw a new exception, which would mean the compiler would have to distinguish from just re-throwing the caught exception and throwing a new exception.

So why would you want the compiler to prevent you form doing something that 1) is not illegal and 2) could be useful?

Upvotes: 15

Related Questions