c# - 可能有意重新抛出 Resharper 异常

标签 c# exception resharper

考虑这种方法(请原谅 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”行上收到一条警告,提示“Exception rethrow possibly intended”。但显然在这种情况下,这不是本意,因为 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;

最佳答案

也许我没理解这个问题,所以如果我说错了,请纠正我。

这里有两种情况:

  1. 首先是你捕获了 原始异常。然后你包装 它在一个新的异常实例中作为 内部异常,然后抛出 新的一个。在这种情况下不会丢失任何信息(内部异常会保留所有信息),因此不会发出警告。

  2. 第二个是你捕获并 重新抛出原来的异常。如果你重新 throw ,你 不应该使用“throw e”,因为它 将篡改堆栈跟踪。 这就是 ReSharper 打印一个 警告。要重新抛出捕获的异常,您应该单独使用“throw”关键字。

this question 的答案比我能更好地解释它。由于微妙的副作用和大量的人弄错了这个细节,我个人认为 re-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;
}

关于c# - 可能有意重新抛出 Resharper 异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1776600/

相关文章:

exception - .NET Core-如何捕获StackOverflowException

c# - Resharper 为 ReactiveUI 的 ReactiveObject 创建自定义重构

unit-testing - ReSharper错误: "The output has reached the limit and was truncated. To view the full output use ' Show Stack Trace in a new window' action.“

c# - 第三方引用的不明确调用

c# - 跨不同 Linq-to-SQL 上下文的实体相等性

c# - 抛出 FileLoadException 或只是 IOException

java - ConcurrentModificationException 但没有从 ArrayList 中删除任何内容

c# - 用于查找数组中少数元素之和的 ParallelFor 代码(子集问题)

http - 在 Struts 2 中处理错误页面

.net - 在不使用 ReSharper 的情况下从 Visual Studio 中使用 dotPeek