【问题标题】:Why does resharper say 'Catch clause with single 'throw' statement is redundant'?为什么 resharper 会说“带有单个 'throw' 语句的 Catch 子句是多余的”?
【发布时间】:2010-11-04 09:21:57
【问题描述】:

我认为抛出异常是一种很好的做法,可以让它冒泡到 UI 或您记录异常并通知用户的地方。

为什么 resharper 说它是多余的?

try
{
    File.Open("FileNotFound.txt", FileMode.Open);
}
catch
{
    throw;
}

【问题讨论】:

    标签: exception-handling try-catch resharper rethrow


    【解决方案1】:

    因为

    try {
        File.Open("FileNotFound.txt", FileMode.Open);
    } catch {
        throw;
    }
    

    没有什么不同
    File.Open("FileNotFound.txt", FileMode.Open);
    

    如果对 File.Open(string, FileMode) 的调用失败,那么在任一示例中,完全相同的异常都会到达 UI。

    在上面的catch 子句中,您只是捕获并重新抛出异常,而无需执行任何其他操作,例如记录日志、回滚事务、包装异常以向其添加附加信息或任何其他操作。

    然而,

    try {
        File.Open("FileNotFound.txt", FileMode.Open);
    } catch(Exception ex) {
        GetLogger().LogException(ex);
        throw;
    }
    

    不会包含任何冗余,ReSharper 不应抱怨。同样,

    try {
        File.Open("FileNotFound.txt", FileMode.Open);
    } catch(Exception ex) {
        throw new MyApplicationException(
            "I'm sorry, but your preferences file could not be found.", ex);
    }
    

    不会是多余的。

    【讨论】:

    • 有一个接球再投球与没有球球并不完全相同。抛出站点和第一个成功捕获之间的每个捕获块的异常过滤器将在任何 finally 块执行之前运行; catch-and-rethrow 将导致其中的所有 finally 块在其外部的任何异常过滤器运行之前运行。顺便说一句,如果在 catch-and-rethrow 之后是另一个更通用的 catch 块,它会做某事(因此 catch-and-rethrow 将用于绕过后一个 catch 块),那么 resharper 会更高兴吗?
    【解决方案2】:

    因为上面的语句具有与不存在相同的行为。同写:

    File.Open("FileNotFound.txt", FileMode.Open);
    

    【讨论】:

    • 是的。不要抓住你不会处理的东西。
    • 是的。如果您要处理异常,请将其放入 try/catch 中。如果您不关心抛出的异常,请不要将其放在 try/catch 中......我认为它只会在上游进一步处理时混淆堆栈跟踪。
    • @John Weldon - 如果您使用“throw”而不是“throw ex”,堆栈跟踪将保持不变。
    • @Twisted:堆栈跟踪保持不变,但如果没有处理异常,为什么要捕获它?
    • @John Weldon - 是的,我同意,只是指出投掷接球并不一定会混淆堆栈。有时我会尝试...catch 进行日志记录,记录错误,然后使用 throw 保留堆栈。
    【解决方案3】:

    因为它是多余的。

    【讨论】:

    • 从什么时候开始把这个问题说成是一个真正的答案:)?
    • 大声笑,我尝试添加冗余标签两次.. 但是,它失败了。
    • 但我想我也可以添加冗余。
    【解决方案4】:

    因为 try 中的代码已经在抛出异常。

    如果除了重新抛出异常之外,您还打算在 catch 块中执行其他操作时,您只想捕获并重新抛出异常。

    【讨论】:

      【解决方案5】:

      你在catch块中没有做任何处理,只是再次抛出了异常。

      它会警告你,因为在那里设置 try...catch 块是没有意义的。

      另外,另一个很好的提示是“throw ex”不会保留堆栈跟踪,但“throw”会。

      【讨论】:

        【解决方案6】:

        值得注意的是,虽然...

        try
        {
            DoSomething();
        }
        catch
        {
            throw;
        }
        

        ...是冗余的,以下不是...

        try
        {
            DoSomething();
        }
        catch (Exception ex)
        {
            // Generally a very bad idea!
            throw ex;
        }
        

        第二个代码 sn-p 在我之前继承的几个项目的代码库中很常见,它具有隐藏原始异常的堆栈跟踪的讨厌效果。以这种方式抛出刚刚捕获的异常意味着堆栈跟踪的顶部处于throw 级别,没有提及DoSomething 或任何嵌套方法调用实际上导致了异常。

        祝你调试代码好运!

        【讨论】:

        • R# 可以设置为警告后者“可能不是故意的”。
        猜你喜欢
        • 2016-11-22
        • 1970-01-01
        • 2013-10-02
        • 2018-11-30
        • 1970-01-01
        • 1970-01-01
        • 2010-10-14
        • 1970-01-01
        相关资源
        最近更新 更多