永远不要捕获的异常情况

5
我知道有一些异常类型无法在catch块中捕获,比如.NET 2.0中的StackOverflowException。我想知道哪些其他异常不建议捕获或与不良实践相关联。
我希望使用此异常类型列表,在每次使用catch块中的Exception时进行检查:
private static readonly Type[] _exceptionsToNotCatch = new Type[] { typeof(StackOverflowException) };

// This should never throw, but should not swallow exceptions that should never be handled.
public void TryPerformOperation()
{
    try
    {
        this.SomeMethodThatMightThrow();
    }
    catch (Exception ex)
    {
        if (_exceptionsToNotCatch.Contains(ex.GetType()))
            throw;
    }
}

编辑

我觉得我没有提供一个很好的例子。试图在沟通自己的意思时让例子变得琐碎是其中的一个问题。

我从不自己抛出异常,我总是捕获特定的异常,只有在以下情况下才捕获异常:

try
{
    this.SomeMethodThatMightThrow();
}
catch (SomeException ex)
{
    // This is safe to ignore.
}
catch (Exception ex)
{
    // Could be some kind of system or framework exception, so don't handle.
    throw;
}

我的问题更多是学术性质的。什么样的异常只由系统抛出,不应该被捕获?我担心的情况更像这样:

try
{
    this.SomeMethodThatMightThrow();
}
catch (OutOfMemoryException ex)
{
    // I would be crazy to handle this!
    // What other exceptions should never be handled?
}
catch (Exception ex)
{
    // Could be some kind of system or framework exception, so don't handle.
    throw;
}

这个问题的灵感来自于以下内容: 在 System.Data.Entity, Version=3.5.0.0 中的 System.Data.EntityUtil.IsCatchableExceptionType(Exception)。

我认为真正的解决方案是不要捕获“Exception”。只捕获你准备处理的异常。如果你对异常没有真正的应对措施,那么让它自然抛出往往比吞下它更好。 - Matt Greer
接下来是对@MattGreer所说的内容的补充。你现在要做的事情与处理异常的正确方式相反。应该捕获并处理你可能预料到的异常。如果出现问题导致应用程序崩溃,那么说明你需要让异常处理更加健壮。而这种方法并不能增强其健壮性。 - spender
1
我对这个问题有点困惑(尽管下面给出的答案是完美的)。你是在问什么是不应该捕获的吗?还是说什么是不能捕获的?因为你一开始给出了一个不能被捕获的例子...但最后又提到了什么是“不可取”的。 - Simon Whitehead
1
也许你会觉得这篇文章很有趣。 - Alessandro D'Andria
4个回答

19
我想知道还有哪些异常不建议捕获,或者与不良实践相关。
以下是您不应该捕获的所有异常列表:
1. 任何你不知道如何处理的异常
以下是异常处理的最佳实践:
如果您不知道如何处理异常,请不要捕获它。
这听起来可能有点刻薄,但两者都是正确的,这就是您需要知道的全部。

1
一针见血。+1 - spender
2
@patxy:当然,你刚刚捕获的那个异常你打算怎么处理? - user1228
1
@patxy:当你的应用程序出现异常时,记录下来是必要的。但是,也要让它过去。一旦你知道了引发异常的代码和原因,就可以设计策略来减轻这些异常。你现在知道如何处理异常了,因此可以捕获它。 - user1228
2
这并不总是你想要的。例如,如果一个IDE插件提供了语法高亮器,编辑器可以捕获高亮器抛出的“大多数”异常,并通过禁用剩余会话的语法高亮来响应。重要的问题是在这种情况下不应该捕获哪些异常,这正是OP所问的问题。在我的工作中,我将这组异常类型称为“关键异常”,这是我从ErrorHandler.IsCriticalException()中获取的。 - Sam Harwell
1
虽然当时我找不到这篇帖子,但我正在寻找类似于https://dev59.com/um035IYBdhLWcg3wSOCr#5508733的东西。我认为你的答案确实很到位 - 不要捕获我不理解的异常。 - CShearholdt
显示剩余5条评论

2

catch块中使用Exception将捕获所有可捕获的异常。我建议您只指定需要捕获的异常,让您不想捕获的异常溢出。例如:

try
{

}
catch(SqlException sqlex)  //specific to database calls
{
   //do something with ex
}
catch(FormatException fex) //specific to invalid conversion to date, int, etc
{
   //do something with ex
}
catch(Exception ex)
{
    //I didn't know this exception would be thrown
    //log it for me or Rethrow it
}

除了那个列表中的异常,任何其他异常都不会被捕获


2

一般情况下,这样做不是一个好主意。

您应该捕获可能性最小的异常,并且只有在执行程序时安全时才继续执行。例如,如果要打开文件,捕获与文件访问/权限错误相关的异常是完全合理的,但不太可能发生其他情况。当然,你不会想要捕获一个OutOfMemoryException然后盲目地继续执行。它们是非常不同的错误!

如果您采用一项普遍规则来捕获异常,那么不能保证您的程序能够安全地继续执行,因为您没有对特定情况进行响应,只是应用一种不适合所有情况的解决方案。


1

好的,我们已经确定这不是一个好主意。我们也已经确定SO上的程序员更喜欢从他们高傲的位置发表意见,而不是递给你一把刀让你自己刺死自己,所以对于那些有自杀倾向的人,让我们从以下几点开始:

(删除了我的列表并将SO简化为指向汉斯的列表)

https://dev59.com/um035IYBdhLWcg3wSOCr#5508733


@HansPassant指向了他在另一个问题上的出色回答,因此我将更新这个答案以指向那个回答。https://dev59.com/um035IYBdhLWcg3wSOCr#5508733 - Luke Puplett

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接