[英]Resharper Exception rethrow possibly intended
考虑一下这种方法(原谅Chuck Norris幽默的悲惨尝试:)):
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;
}
}
在resharper中,我收到一条警告“throw e”行说“异常重新抛出可能意图”。 但显然在这种情况下,这不是意图,因为e可以包装在ChuckNorrisException中,如果我只是使用“throw”,那么包装的异常就不会被抛出。
我知道我可以抑制resharper警告,但是如果我没有弄错的话,它会在所有情况下关闭。 我只是想知道是否还有其他人遇到过此事。 我发现的唯一解决方法是创建另一个异常变量(例如e2),然后抛出它。 这可能是我能在这里做的最好的。 似乎resharper可以检测到这个问题并且足够聪明,知道如果e被修改,那么抛出e就可以了。
谢谢。
[编辑]对不起,我忘记了一步。 在抛出之前,我需要记录异常,所以我不能这样做:
e = e is DivideByZeroException ? new ChuckNorrisException("Only Chuck Norris can divide by 0!", e) :
e;
throw e;
我要做:
e = e is DivideByZeroException ? new ChuckNorrisException("Only Chuck Norris can divide by 0!", e) :
e;
LogException(e);
throw e;
也许我不理解这个问题,所以如果我有错误的结论,请纠正我。
这里有两种情况:
首先是你抓住原来的例外。 然后将其作为内部异常包装在新的异常实例中,然后抛出新的异常。 在这种情况下不会丢失任何信息(内部异常保留所有信息),因此不会给出警告。
第二个是你抓住并重新抛出原始异常。 如果你重新抛出,你永远不应该使用“throw e”,因为它会篡改堆栈跟踪。 这就是ReSharper打印警告的原因。 要重新抛出捕获的异常,您应该自己使用“throw”关键字。
这个问题的答案解释得比我好。 由于微妙的副作用以及使这个细节错误的人数众多,我个人认为重新抛出的语法是有缺陷的。
无论如何,这是对你收到警告的原因的描述。 以下是我要做的事情:
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);
}
*编辑 - 如果您需要记录异常,您可以执行此类操作。 注意:这是我首选的解决方案,因为我认为它读起来更好,并且不像自己查询异常类型那样包含错误:
// 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
}
另一种选择是:
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;
}
这将与您发布的代码具有相同的效果,不应导致警告。
catch (DivideByZeroException de)
{
throw new ChuckNorrisException("Only Chuck Norris can divide by 0!", de);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.