捕获System.Exception总是一个坏习惯吗?

时间:2011-06-30 14:13:33

标签: c# exception-handling

请考虑以下代码,它会抛出三个不同的例外(即System.Configuration.ConfigurationErrorsExceptionSystem.FormatExceptionSystem.OverflowException):

int SomeInt = Convert.ToInt32(ConfigurationManager.AppSettings["SomeIntValue"]);

异常是不同的,因此在实践中我应该有三个不同的catch块来处理每个特定的异常。但是,在这种特殊情况下,所有异常都以相同的方式处理:将日志写入,例如,EventViewer,并显示一条消息,通知配置错误......在这个特定原因中,使用<太糟糕了/ p>

try
{
    int SomeInt = ConfigurationManager.AppSettings["SomeIntValue"];
}
catch (Exception ThisException)
{
    /* Log and display error message. */
}

或者我应该使用三个catch块并在每个块中重复代码?

6 个答案:

答案 0 :(得分:8)

有关此问题的讨论,请参阅C# Exception Handling Fall Through

简而言之,如果您捕获一般异常,则应检查它是否是预期类型之一,如果不重新抛出它。

更新(并且有点超出范围)

还有几次我认为做一个全部捕获是有效的。这是非常罕见的,但有时在web服务中,或者如果你在asp.net中的后台线程上做了一些事情,那么将重新启动整个应用程序,如果你已经依赖它,人们可能会失去他们的会话。

答案 1 :(得分:4)

捕获System.Exception是不好的做法。 。 。或者更好的是,除了应用程序的顶层以外,处理 System.Exception是不好的做法。你应该做的是:

  1. Catch System.Exception
  2. 测试您计划以相同方式处理的类型的例外
  3. 如果Rethrow不是其中之一的话。
  4. 示例代码:

    catch (Exception ex)
    {
        if (ex is FormatException || ex is OverflowException || ex is ConfigurationErrorsException) {
            CommonHandler();
        }
        else {
            throw;
        }
    }
    

答案 2 :(得分:2)

我不认为这是不好的做法。如果你想要的功能是“每当这段代码抛出一个异常,然后采取这些行动”,那么我认为捕捉System.Exception是完全合适的。

在我看来,包装一个非常具体的框架函数而不是一大块自定义代码的事实也有帮助。

答案 3 :(得分:1)

这不一定是不好的做法,当你在catch区块做愚蠢的事情时,通常会发生不良做法。捕获基本异常类是一个很好的安全措施,假设您在发生错误时需要执行某些操作。捕获特定异常类的情况最好在该特定类为您提供可以处理的信息时显示,例如,捕获SqlException可以帮助您查看特定于该类的某些属性并让您对该问题采取行动。

人们常常会抓住异常并做一些愚蠢的事情,比如创建新的异常,甚至更糟糕的是,吞下异常细节。

经常错过的模式是你可以抓住,进行重新渲染。

catch(Exception ex)
{
 //do something
 throw;
}

因此保留了异常细节。

答案 4 :(得分:1)

在这种特殊情况下,完全可以使用不同的catch块,因为可以采取不同的操作,具体取决于您获得的异常。

对于前两个,您可以静默设置合理的默认值,以免不必要地骚扰用户,然后希望在保存文件时问题自行解决,对于后一个例外,您可以询问用户是否要继续加载过程(在这种情况下,您设置了合理的默认值),因为配置文件显然已损坏。

一般来说,我的想法是这样的:我是否需要针对不同类型的异常采取不同的行动?通常情况下,答案是否定的,所以空白{{ 1}}(如果异常总是致命的话,甚至根本没有catch(Exception ex){ /* log... */ }就足够了。

编辑:空白检查时为空,不是空块:)

答案 5 :(得分:1)

实际需要什么,但.net异常层次结构没有提供,是一种区分异常的简洁方法,这意味着“请求的操作没有发生,但系统状态基本上是正常的,除非隐含的程度没有发生的操作“来自那些意味着”CPU处于激烈状态,甚至试图保存当前用户的工作也可能不会让事情变得更糟。“有很多背景,其中一个人应该努力捕捉第一类的所有例外,而理想情况下不会捕捉第二类的例外。虽然有两个以上的渐变,但通常在捕获异常时,并不真正关心InvalidArgumentException或InvalidOperationException之间的区别;人们关心的是整个系统状态是有效还是已损坏。

实际上,如果有人打电话给,例如一个文件导入插件,它抛出一个异常,我不是很确定可以做的除了尝试捕获并重新抛出非常糟糕的异常,而所有其他异常都会出现“此文件无法打开”对话框。希望此时系统的状态基本上与用户未尝试打开文件的情况一样,但如果没有一些标准化的方法来指示异常严重性,我认为没有任何方法可以确定。

顺便说一下,如果我有我的druthers,会有一个类ExceptionBase,所有异常都会从中派生出来;大多数异常都派生自Exception(后者又派生自ExceptionBase),但ThreadAbortException,StackOverflowException,OutOfMemoryException等内容将从CriticalException派生。这样一来,人们就可以捕获大多数“意想不到的”异常而不会意外地扼杀真正的异常。