Exception 为什么不抓住一般例外

Exception 为什么不抓住一般例外,exception,Exception,我的VS刚刚告诉我 警告2 CA1031:Microsoft.Design:修改“Program.Main(string[])以捕获比“exception”更具体的异常,或重新显示该异常 我为什么要这样做?如果我这样做了,并且没有捕获所有异常来处理它们,我的程序就会在所有流行的报告屏幕上崩溃。我不希望我的用户得到这样的错误废话 为什么我不应该一次捕获所有异常,向用户显示一个很好的警告:“出了问题,不要在意,我会处理的,只是耐心一点” 编辑:刚才看到我这里有一个复制品,很抱歉 编辑2:澄清事情;我

我的VS刚刚告诉我

警告2 CA1031:Microsoft.Design:修改“Program.Main(string[])以捕获比“exception”更具体的异常,或重新显示该异常

我为什么要这样做?如果我这样做了,并且没有捕获所有异常来处理它们,我的程序就会在所有流行的报告屏幕上崩溃。我不希望我的用户得到这样的错误废话

为什么我不应该一次捕获所有异常,向用户显示一个很好的警告:“出了问题,不要在意,我会处理的,只是耐心一点”

编辑:刚才看到我这里有一个复制品,很抱歉


编辑2:澄清事情;我会在捕捉到任何异常后退出程序!我只是不想让我的用户看到控制台应用程序中出现未处理异常时显示的“向microsoft报告”对话框

简单回答:你应该修复你的bug。找到引发异常的位置,除非它超出您的控制范围,否则请修复它。
同时,捕获(不重新触发)所有类型的异常也违反了异常中立性。通常情况下,您不想这样做(尽管在
main
中捕获异常看起来像是特例)

当您捕获一般异常时,您会得到一个副作用,即潜在地向用户隐藏运行时问题,这反过来会使调试复杂化。此外,通过捕获常规异常,您忽略了一个问题(您可能会将其扔到其他地方)。

您应该处理您能够处理的确切异常,并让所有其他异常冒泡。如果它向用户显示一条消息,表示您不太清楚您可以处理什么。

您可以设置try-catch来捕获多个不同的行为类型,并根据该类型处理异常。对于框架中的大多数方法和属性,您还可以看到它们能够抛出哪些异常。因此,除非您是从一个非常小的代码块捕获异常,否则您可能应该捕获特定的异常。

因为不分青红皂白地吞下(捕获)异常(然后继续)的程序不能被依赖于完成预期的任务。这是因为您不知道什么样的异常被“忽略”。如果出现溢出或内存访问错误,导致从金融账户中借记错误金额,该怎么办?如果它把船驶入冰山而不是远离冰山呢?意外故障应始终导致应用程序终止。这迫使开发过程识别并纠正发现的异常(演示过程中的崩溃是一个极好的激励因素),并且在生产过程中,当软件遇到“意外”无法完成其设计任务时,允许适当设计的备份系统作出反应

编辑:澄清UI组件和服务或中间件组件之间的区别


在服务或中间件组件中,如果没有用户从代码运行所在的同一进程空间与代码组件交互,则该组件需要将异常“传递”到启动其当前正在处理的调用的任何客户端组件。不管有什么例外,它都应该尽一切可能做到这一点。然而,情况仍然如此,在发生意外或意外异常的情况下,组件应该最终终止它正在运行的进程。对于预期或预期的异常,应进行开发分析,以确定对于该特定异常,组件及其主机进程是否可以继续运行(处理未来的请求),或者是否应终止

吞咽异常是一种危险的做法,因为:

  • 当它实际失败时,它会让用户认为它成功了
  • 它可以将您的应用程序置于您没有计划的状态
  • 这会使调试复杂化,因为当您处理奇怪/损坏的行为而不是堆栈跟踪时,很难找出故障发生的位置
正如你可能想象的那样,这些结果中的一些可能是极其灾难性的,因此正确地做这件事是一个重要的习惯

最佳实践

首先,防御性地编写代码,使异常不会超出必要的范围。它们在计算上很昂贵

尽可能在粒度级别处理预期的异常(例如:
FileNotFoundException

对于意外异常,可以执行以下两种操作之一:

  • 让它们正常冒泡,造成碰撞
  • 抓住他们,优雅地失败
优雅地失败?

假设您在ASP.Net中工作,您不希望向用户显示死亡的黄屏,但也不希望对开发团队隐藏问题

在我们的应用程序中,我们通常在
global.asax
中捕获未处理的异常,然后进行日志记录并发送通知电子邮件。我们还显示了一个更友好的错误页面,可以在
web.config
中使用
customErrors
标记进行配置

这是我们的最后一道防线,如果我们最终收到一封电子邮件,我们会立即投入其中

这种类型的模式与吞咽异常不同,在吞咽异常时,您有一个空的Catch块,它的存在只是为了“假装”异常没有发生

其他注释

在VS2010中,有一种叫做intellitrace的东西即将出现,它将允许您通过电子邮件将应用程序状态发送回主页,并逐步执行代码,在发生异常时检查变量值,等等。这将是非常有用的。

有一种方法。我之所以使用它就是为了这个确切的原因(为了记录日志而捕获一般异常),而且它非常方便。Wh
#if DEBUG
  yadda(); // Check only specific Exception types here
#else
  try
  {
    yadda();
  }
  catch (Exception e)
  {
     ShowMessage(e); // Show friendly message to user
  }
#endif
<customErrors mode="RemoteOnly" defaultRedirect="~/CustomErrorPage.aspx" redirectMode="ResponseRewrite" />