.NET的一般异常处理策略

Bob*_*orn 12 .net c# exception-handling exception-logging

我习惯在每种方法中使用try/catch块.这样做的原因是我可以在违规点捕获每个异常并记录它.从我的阅读和与他人的对话中我理解,这不是一种流行的观点.人们应该只抓住人们准备处理的事情.但是,如果我没有抓到违规点,那么就有可能永远不会记录这种违规行为并了解它.注意:当我抓住并且不处理时,我仍然会抛出.这允许我让异常传播到将处理它的东西,但仍然让我在违规点记录它.

那么......如何在每个方法中避免try/catch,但仍然在错误发生时记录错误?

Joh*_*ers 18

不,不要抓住一切.异常在堆栈上向上传播.您所要做的就是确保在异常到达堆栈顶部之前捕获该异常.

这意味着,例如,您应该使用try/catch块包围事件处理程序的代码.事件处理程序可能是"堆栈顶部".对于ThreadStart处理程序或来自异步方法的回调也是如此.

您还希望捕获层边界上的异常,但在这种情况下,您可能只想将异常包装在特定于层的异常中.

对于ASP.NET,您可以决定允许ASP.NET Health Monitoring为您记录异常.

但你肯定不需要在每种方法中捕获异常.这是一个重要的反模式.我会大声反对你用这种异常处理来检查代码.


Arn*_*psa 9

您可以在堆栈跟踪中查看所有内容 - 无需尝试/捕获每个方法.

坚持几条规则:

  1. 仅当您要使用自定义异常类型时才使用try/catch
  2. 仅当上层需要知道时才定义新的异常类型
  3. 尝试/捕获顶层而不是为每个方法执行此操作


Gar*_*ill 5

好吧,在阅读了所有的答案后,都说你应该在顶层进行一次 try/catch,我将用另一种观点来权衡。

我不会在每个方法中都添加 try/catch,远非如此。但我在我预计会失败的代码部分(例如打开文件)以及我想要向异常添加附加信息的位置(要在链的更高位置记录)使用 try/catch。

堆栈跟踪说明和消息“权限被拒绝”可能足以让您作为程序员找出问题所在,但我的目标是向用户提供有意义的信息,例如“无法打开文件'C: \lockedfile.txt'。权限被拒绝。”。

如:

private void DoSomethingWithFile(string filename)
{
    // Note: try/catch doesn't need to surround the whole method...

    if (File.Exists(filename))
    {
        try
        {
            // do something involving the file
        }
        catch (Exception ex)
        {
            throw new ApplicationException(string.Format("Cannot do something with file '{0}'.", filename), ex);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我还想提一下,即使是那些说“只有一次 try/catch”的人可能仍然会在整个代码中使用 try/finally,因为这是保证正确清理等的唯一方法。

  • 仅供参考,“ApplicationException”已被弃用。我也不会捕获“Exception”,而只会捕获与我在“try”块中所做的事情相关的异常,例如“IOException”。 (2认同)