捕获通用非致命异常

Oha*_*der 7 .net c# exception-handling

传统观点认为我们应该只捕获我们期望的特定异常类型:

try
{           
    int.Parse(str); //I am aware of TryParse(), this is just for the sake of example
}
catch (FormatException ex)
{
    Console.WriteLine (ex);
}
catch (OverflowException ex)
{
    Console.WriteLine (ex);
}
Run Code Online (Sandbox Code Playgroud)

但是,有时我们并不关心发生了哪个异常(只要它不是致命的),可能是因为我们只是想让用户知道发生了错误.在这些情况下,我们可以这样做:

try
{           
    Foo();
}
catch (Exception ex)
{
    if (IsCriticalException(ex))
    {
        Environment.FailFast("System Error", ex);
    }

    Console.WriteLine ("Error running Foo: {0}", ex);
}   
Run Code Online (Sandbox Code Playgroud)

在哪里IsCriticalException可以类似地实施System.ClientUtils.IsCriticalException.由于以下几个原因,我一般都赞成这种方法:

  1. 有些方法可能抛出许多异常类型,捕获它们可能很麻烦.例如,File.Open可以抛出九种不同类型的异常.
  2. 某些方法可能会抛出未记录的异常.这可能是由于缺少文档,或者是由于某些错误.例如,由于一个模糊的bug ,ICommunicationObject.Close实际上可能会抛出ArgumentException.有些方法甚至不能静态地知道它们可以抛出哪些异常,因为它们动态地加载其他模块/插件.据推测,他们可以用他们自己已知的例外情况包装所有这些"外部"例外,但我相信并非所有例外都有.

这种方法的批评者认为方法的例外是其合同的一部分.如果抛出的异常不是本合同的一部分,我们应该假设其状态已损坏.我们还会在方法中发现一个错误(因为我们已经吞下了意外的异常,否则我们就不会发现这个错误).然后我们可以将这个bug传递给框架的开发人员,这是一个胜利 - 特别是如果这些开发人员在我们公司,所以我们"帮助自己"可以这么说.

我承认,批评者提出了有效的观点,但我觉得他们有点理想主义.实际上,我认为通用的非致命异常捕获在很多情况下都是有意义的.我有道理吗?

相关阅读:

nvo*_*igt 1

传统观点认为我们应该只捕获我们期望的特定异常类型

实际上,我认为你应该准确地捕获那些你可以处理的异常。仅仅捕获异常并重新抛出它们是没有用的,并且让那些本来可以解决的异常通过也是没有意义的。

在上面的示例中,我认为有一个包罗万象的块就可以了,毕竟不转换该字符串是一个可恢复的错误,无论弹出什么异常(除了 OutOfMemoryException ,它无论如何都无法处理,因为任何尝试处理会使用内存)。