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

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

Example:

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

"throw ex" is bad practice because the stack trace is truncated below the method that failed. So it's harder to debug the code. Therefore, the code should be:

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

My question is, why does the compiler allow this (or does not display a warning message?) Is there a case that throw throw is useful?

+6
source share
4 answers

throw new Exception(); or throw ex; both will use the same language rules to allow the throwing of an exception object (whether new or existing). If you want to add additional information, with the exception of this option, this is useful.

See: How: Explicit Exception Exceptions - MSDN

You can explicitly throw an exception using the throw statement. You can also throw a catch exception again using the throw statement. It is good coding practice to add information to an exception that is re-selected to provide additional information during debugging.

Since for both, throw new Exception() and throw ex; identical language rules are required, in fact it is not a compiler to distinguish between the two.

A simple exception to an existing exception without making any changes to the exception object will use the same language construct.

Just as @D Stanley pointed out in the answer that truncating a stack trace may be desirable.

As for your question about the compiler, which does not warn about this, this does not mean that the compiler should warn about bad practices, there are code analysis tools. For example, a managed code management tool will raise a warning for throw ex; CA2200: repeat to save stack information

+4
source

Is there a case that throw throw is useful?

Of course - sometimes you want to truncate the stack trace - so as not to expose implementation details, etc. At other times, you might want to throw a new exception, which would mean that the compiler would have to distinguish from just throwing the caught exception again and throw a new exception.

So, why do you want the compiler to not allow you to create something that 1) is not illegal and 2) can be useful?

+15
source

While compilers can, of course, prevent some obvious programming errors, they cannot follow best practices like this without causing some inevitable false positives along the way.

Programmers can choose to modify the contents of the exception inside the exception handler or instead introduce a completely new exception. In both cases, a warning message about an exception from the exception handler will be annoying and useless.

One case where it makes sense to change the internal state of an exception occurs when you throw an exception from a recursive function. Consider a recursive descent analyzer reporting an error from several layers along a recursive chain. Each call level can potentially add more useful information to the useful information. However, wrapping the exceptions of each subsequent layer in a new exception in this case is impractical, because in the end you get a recursive data structure, which is a flat list. One viable solution for such situations would be to create a custom exception in which each catcher can add additional information before re-throwing. Since a function (or, more precisely, a group of functions) is recursive, the place in the code from which the original exception was selected is less important than the completeness of the context, leading to the exception in the first place.

This does not mean that searching for such situations is completely useless: code checking tools such as ReSharper can certainly help programmers keep track of such problems. The compiler, however, is a poor choice for a watchdog with best practice, because for the most part the compiler should do what they say.

+1
source

I think I'm considering catch culprit when you just want to distribute something on the stack. Should catch completely avoided 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 wrote a lot of bSucceded , and I don't think I ever wrote a throw inside catch without adding a new Exception (). (At least since I first studied Java in 99 or so.)

I assume that a huge number of possible ways to deal with this is why they allow you to do what you want here, instead of trying to block it.

0
source

Source: https://habr.com/ru/post/972028/


All Articles