Consider this method (pardon the sad attempt at Chuck Norris humor :) ):
public class ChuckNorrisException : Exception
{
public ChuckNorrisException()
{
}
public ChuckNorrisException(string message)
: base(message)
{
}
public ChuckNorrisException(string message, Exception cause)
: base(message, cause)
{
}
protected ChuckNorrisException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
}
static void ExceptionTest(double x)
{
try
{
double y = 10 / x;
Console.WriteLine("quotient = " + y);
}
catch (Exception e)
{
e = e is DivideByZeroException ? new ChuckNorrisException("Only Chuck Norris can divide by 0!", e) :
e;
throw e;
}
}
In resharper, I get a warning on the "throw e" line saying "Exception rethrow possibly intended". But obviously in this case that's not the intention, since e could be wrapped in ChuckNorrisException, and if I just use "throw", that wrapped exception wouldn't get thrown.
I know I can suppress the resharper warning, but then it will be turned off for all scenarios if I'm not mistaken. I just wondered if anybody else had encountered this. The only workaround I've found is to make another exception variable (e2, for example), and throw that. That may be the best I can do here. Seems like resharper could detect this issue though and be smart enough to know that if e is modified, then throw e is ok.
Thanks.
[EDIT] Sorry, I forgot a step. Before the throw, I need to log the exception, so I can't just do:
e = e is DivideByZeroException ? new ChuckNorrisException("Only Chuck Norris can divide by 0!", e) :
e;
throw e;
I have to do:
e = e is DivideByZeroException ? new ChuckNorrisException("Only Chuck Norris can divide by 0!", e) :
e;
LogException(e);
throw e;
Catch and rethrow exception Medium Catching and re-throwing an exception without further actions is redundant and wasteful. Instead, it is recommended to re-throw custom exception type and/or log trace for debugging.
An exception caught by one catch can be rethrown so that it can be caught by an outer catch. To rethrow an exception, you simply specify throw, without specifying an expression.
When an exception is caught, we can perform some operations, like logging the error, and then re-throw the exception. Re-throwing an exception means calling the throw statement without an exception object, inside a catch block. It can only be used inside a catch block.
While throw is a keyword that singles the occurrence of an exception during the program execution, throw ex is a keyword in C# that allows the programmers to indicate the occurrence of an exception which resets the stack trace. Thus, this is the main difference between throw and throw ex in C#.
Maybe I'm not understanding the question, so please correct me if I've got the wrong end of the stick.
There's two cases going on here:
The first is that you catch the original exception. You then wrap it in a new exception instance as the inner exception, then throw the new one. No information is lost in this case (the inner exception preserves all information), so no warning is given.
The second is that you catch and re-throw the original exception. If you re-throw, you should never use "throw e", as it will tamper with the stack trace. This is why ReSharper is printing a warning. To re-throw the caught exception, you should use the "throw" keyword on its own.
The answer to this question explains it better than I can. Due to the subtle side effects and the sheer number of people who get this detail wrong, I personally view the re-throw syntax as flawed.
Anyway that's a description of why you're getting a warning. Here's what I'd do about it instead:
catch(DivideByZeroException e)
{
// we don't catch any other exceptions because we weren't
// logging them or doing anything with the exception before re-throwing
throw new ChuckNorrisException("Useful information", e);
}
*Edit -- if you need to log exceptions, you can just do something like this instead. Note: This is my preferred solution as I think it reads better and is less likely to contain an error than querying for exception types yourself:
// catch most specific exception type first
catch(DivideByZeroException e)
{
Log(e);
throw new ChuckNorrisException("Useful information", e);
}
catch(Exception e) // log & re-throw all other exceptions
{
Log(e);
throw; // notice this is *not* "throw e"; this preserves the stack trace
}
Another alternative would be:
catch(Exception e)
{
Log(e);
if(e is DivideByZeroException)
{
// wrap + throw the exception with our new exception type
throw new ChuckNorrisException("useful info", e);
}
// re-throw the original, preserving the stack trace
throw;
}
This will have the same effect as the code you have posted and should not cause the warning.
catch (DivideByZeroException de)
{
throw new ChuckNorrisException("Only Chuck Norris can divide by 0!", de);
}
}
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