考虑这种方法(原谅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;
答案 0 :(得分:31)
也许我不理解这个问题,所以如果我的错误结束,请纠正我。
这里有两种情况:
首先是你抓住了 原始例外。然后换行 它在一个新的异常实例中 内部异常,然后抛出 新的一个。在这种情况下没有信息丢失(内部异常保留所有信息),因此没有给出警告。
第二个是你抓住了 重新抛出原始异常。如果你重新投掷,你 永远不应该使用“扔e”,因为它 将篡改堆栈跟踪。 这就是ReSharper打印的原因 警告。要重新抛出捕获的异常,您应该自己使用“throw”关键字。
this question的答案比我更好地解释了它。由于微妙的副作用和错误的人数,我个人认为重新抛出的语法是有缺陷的。
无论如何,这是对为什么您的警告的描述。以下是我要做的事情:
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;
}
答案 1 :(得分:2)
这与您发布的代码具有相同的效果,不应导致警告。
catch (DivideByZeroException de)
{
throw new ChuckNorrisException("Only Chuck Norris can divide by 0!", de);
}
}