捕获System.Exception总是一种糟糕的做法吗

本文关键字:一种 Exception System 捕获 | 更新日期: 2023-09-27 18:00:51

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

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

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

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

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

捕获System.Exception总是一种糟糕的做法吗

有关此问题的讨论,请参阅C#异常处理失败。

简言之,如果您捕获了一般的Exception,您应该检查它是否是预期的类型之一,如果不是重新抛出它

更新(有点超出范围)

还有几次,我认为一网打尽是有效的。这是非常罕见的,但有时在Web服务中,或者如果你在asp.net的后台线程上做了一些事情,就会重新启动整个应用程序,如果你依赖它,人们可能会失去会话。

捕获System.Exception是一种糟糕的做法……或者更好的是,在应用程序的顶级之外的任何地方处理System.Exception都是一种不好的做法。你应该做的是:

  1. Catch System.Exception
  2. 测试计划以相同方式处理的类型的异常
  3. 如果它不是其中之一,请重试

示例代码:

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

我不认为这是一种糟糕的做法。如果你想要的功能是"每当这个代码抛出异常,就采取这些操作",那么我认为捕捉System.exception是非常合适的。

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

真正需要的是什么,但.net异常层次结构没有提供,是区分异常的一种干净方法,即"请求的操作没有发生,但系统状态基本上很好,除非操作没有发生"answers"CPU着火了,即使试图保存当前用户的工作也可能不会让事情变得更糟"。"在很多情况下,人们真的应该努力捕捉第一种类型的所有异常,而理想情况下不捕捉第二种类型的异常。虽然除了上面两种之外还有一些级别,但通常在捕捉异常时,人们并不真正关心InvalidArgumentException和InvalidOperationException之间的区别;人们关心的是rall系统状态有效或已损坏。

事实上,如果一个人正在调用例如文件导入插件,并抛出异常,我真的不确定他能做什么,除了尝试捕获并重新抛出非常糟糕的异常,同时让所有其他异常都显示"This file cannot be open"对话框。希望当时的系统状态基本上与用户没有尝试打开文件时的状态相同,但如果没有某种标准化的方式来指示异常严重性,我认为没有任何方法可以确定。

顺便说一句,如果我有自己的druthers,就会有一个类ExceptionBase,所有的异常都会从中派生出来;大多数异常都会从Exception派生(而Exception又会从ExceptionBase派生),但ThreadAbortException、StackOverflowException、OutOfMemoryException等都会从CriticalException派生。这样就可以捕捉到大多数"意外"的异常,而不会意外地扼杀真正糟糕的异常。

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

通常情况下,人们会发现一个异常并做一些愚蠢的事情,比如创建一个新的异常,甚至更糟的是,吞下异常的细节。

一个经常被忽略的模式是,你可以抓住,采取行动,重新思考。

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

从而保留了异常细节。

在这种特殊情况下,完全可以使用不同的catch块,因为可以根据得到的异常执行不同的操作。

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

通常,我的想法是:对于抛出的不同类型的异常,我需要采取不同的操作吗通常情况下,答案是否定的,因此一个空白的catch(Exception ex){ /* log... */ }(如果异常总是致命的,则甚至根本没有catch)就足够了。

编辑:空白复选框中的空白,而不是空块:)