我不应该抓住哪些例外情况?

我有一个运行长批处理的应用程序,可能会抛出许多exception。 如果在批处理中的一个项目期间抛出非关键exception,我只想记录并继续,这样我们可以稍后解决问题,同时让其他批处理项继续。

一些例外,例如OutOfMemoryException ,对整个应用程序来说是毁灭性的,这些我想重新抛出,以便它们冒泡到全局exception处理程序,它将记录错误并停止应用程序。

所以我的问题是,是否有一个合理的短的关键exception列表,我可以在我的下级exception处理程序中重新抛出,同时抑制(记录后)其他所有内容?

谢谢!

编辑:稍微详细说明,这是我的程序的基本结构

 foreach(var item in longItemList) { try { bigDynamicDispatchMethod(item); } catch(Exception ex) { logException(ex); } } 

可能会抛出大量exception,因为这个循环几乎是我应用程序的顶级。 我项目中99%的代码都在调度方法之后。 我在较低级别进行合理的exception处理,但是错误仍然存​​在,我不想在抛出exception后停止批处理中的其他无关进程。

试图找到可以在我的应用程序中的其他地方抛出哪些exception似乎是一项艰巨的任务,似乎更容易获得关键exception的黑名单。

有没有更好的方法来构建我的应用程序来处理这个? 我愿意接受建议。

您不需要“坏”exception列表,默认情况下应将所有内容视为坏内容。 只抓住你可以处理和恢复的东西。 CLR 可以 通知您未处理的exception,以便您可以正确记录它们。 除了黑名单的exception之外,吞下一切都不是修复bug的正确方法。 这只会掩盖他们。 阅读本文和此内容 。

为了传输exception而捕获时不要排除任何特殊exception。

您应该只捕获可以合法处理的exception,而不是在catch子句中创建特殊exception列表。 您不能处理的exception不应被视为非特定exception处理程序中的特殊情况。 以下代码示例演示了为重新抛出特殊exception而错误地测试特殊exception。

 public class BadExceptionHandlingExample2 { public void DoWork() { // Do some work that might throw exceptions. } public void MethodWithBadHandler() { try { DoWork(); } catch (Exception e) { if (e is StackOverflowException || e is OutOfMemoryException) throw; // Handle the exception and // continue executing. } } } 

其他规则很少:

通过在应用程序代码中捕获非特定exception(例如System.Exception,System.SystemException等)来避免处理错误。 有些情况下,处理应用程序中的错误是可以接受的,但这种情况很少见。

应用程序不应处理可能导致意外或可利用状态的exception。 如果您无法预测exception的所有可能原因并确保恶意代码无法利用生成的应用程序状态,则应允许应用程序终止而不是处理exception。

当您了解为什么它将在给定的上下文中抛出时,请考虑捕获特定的exception。

您应该只捕获可以从中恢复的exception。 例如,尝试打开不存在的文件导致的FileNotFoundException可以由应用程序处理,因为它可以将问题传达给用户并允许用户指定不同的文件名或创建文件。 不应处理打开生成ExecutionEngineException的文件的请求,因为无法确定地知道exception的根本原因,并且应用程序无法确保继续执行是安全的。

Eric Lippert将所有exception分为4组:致命,’斩首’,Vexing,外生。 以下是我对Eric的建议的解释:

  Exc. type | What to do | Example ------------|-------------------------------------|------------------- Fatal | nothing, let CLR handle it | OutOfMemoryException ------------|-------------------------------------|------------------- Boneheaded | fix the bug that caused exception | ArgumentNullException ------------|-------------------------------------|------------------- Vexing | fix the bug that caused exception | FormatException from | (by catching exception because | Guid constructor | the framework provides no other way | (fixed in .NET 4.0 | way of handling). Open MS Connect | by Guid.TryParse) | issue. | ------------|-------------------------------------|------------------- Exogenous | handle exception programmatically | FileNotFoundException 

这大致相当于Microsoft的分类:用法,程序错误和系统故障。 您还可以使用FxCop等静态分析工具来强制执行其中一些规则。

不要抓住任何你不知道如何安全处理的例外情况。

捕获Exception是一种特别糟糕的做法,唯一更糟的是没有指定任何托管exception类型的catch(因为它也会捕获非托管exception)。

这个问题将支持更合适的设计:我应该捕获哪些例外 ?

如果您确实需要捕获任何和所有exception并仍然继续,那么您应该同时使用AppDomain和单独的工作进程。 或者将您的主机更改为ASP.NET或任务计划程序,它们已经完成了围绕进程隔离和重试的所有艰苦工作。

除非将HandleProcessCorruptedStateExceptions属性应用于exception处理函数,否则所有“不应由用户代码处理”的exception都已被忽略,因此除了安全地处理exception处理之外,您还可以处理任何其他操作。

我会参考以下文章的建议。

.NET Framework设计准则规则:不要捕获无法处理的exception

http://www.codeproject.com/KB/cs/csmverrorhandling.aspx

同样来自参考文章:

您永远不应该在catch块中捕获System.Exception或System.SystemException

捕获你希望你的代码抛出的错误..当你使用API​​或方法时,看看它将抛出什么exception并只捕获那些..你不应该列出exception列表并始终捕获那些..

  • 阅读msdn googleexception处理最佳实践
  • 永远不要抓住像Exception这样的非特定exception