C# 程序从不尝试从哪些异常中恢复?

C# 程序从不尝试从哪些异常中恢复?,c#,.net,vb.net,C#,.net,Vb.net,异常会对程序产生不同程度的影响。例如,如果引发了OutOfMemoryException,程序可能会中止,但可以安全、适当地处理System.Data.SqlClient.SqlException,而不会使程序处于未知状态 我知道,如果处理不当,任何异常都有可能使程序处于不稳定状态。除了简单地记录日志和抛出堆栈之外,是否存在永远不应该处理的异常 这可能是另一种情况,但任何暗示程序员错误的异常:NullReferenceException,IndexOutOfRangeException,等等。这

异常会对程序产生不同程度的影响。例如,如果引发了
OutOfMemoryException
,程序可能会中止,但可以安全、适当地处理
System.Data.SqlClient.SqlException
,而不会使程序处于未知状态


我知道,如果处理不当,任何异常都有可能使程序处于不稳定状态。除了简单地记录日志和抛出堆栈之外,是否存在永远不应该处理的异常

这可能是另一种情况,但任何暗示程序员错误的异常:
NullReferenceException
IndexOutOfRangeException
,等等。这意味着您的代码中有一个bug,您应该修复它,而不是处理它。

这在很大程度上取决于您的应用程序。大多数应用程序可能会显示错误消息并因
OutOfMemoryException
而死机,但并非全部-例如一个名为SmartRAM的程序(我想就是这个名字),它通过尝试分配越来越多的内存来恢复RAM,直到出现异常-这会导致Windows删除RAM中的所有缓存,给你更多的自由内存


所以这取决于你在做什么。如果作为应用程序专家,您觉得可以安全地从异常中恢复,那么您应该这样做。

这取决于程序中发生异常的位置


一般来说,最好处理您的代码的各个部分想要/知道如何处理的异常,并让其余的冒泡到其他地方处理,或者根本不处理。

这是一个逐案的理论问题,因此答案也将是理论性的。我听过的最好的答案是,“如果你不知道如何处理异常,就不要处理它。”记录一条消息并将异常抛出堆栈是很好的,因为你确实做了一些事情(即使只是表明发生了错误)。但是,捕获错误而不将其抛出堆栈可能会导致隐藏的错误和困难的调试会话

我们一直在做的是实现一个顶级错误处理程序,它将执行一般的错误处理(如记录消息、提醒开发人员等)。在代码的深层未处理的所有异常至少由顶级处理程序处理。代码中可以在较低级别处理的异常肯定会在发生的地方处理

考虑在电子邮件地址列表上循环以向邮件列表发送消息的情况。如果其中一个电子邮件地址的格式不正确,则可能会发生异常,但我们不希望单个电子邮件地址导致其余处理失败。通过处理发生的特定异常类型,我们可以记录它(甚至将电子邮件地址标记为无效),并继续处理列表的其余部分

底线:您是否处理给定的异常类型实际上取决于您的代码是否知道在异常类型发生时如何进行恢复。

不要捕获框架中的System.Exception或System.SystemException 代码,除非你打算重新抛出

不要捕获System.StackOverflowException

以编程方式处理堆栈溢出非常困难。 您应该允许此异常终止进程并使用 调试以确定问题的来源

不要显式捕获System.Runtime.InteropServices.SehexException


典型的异常层次结构有两个主要分支:运行时错误和逻辑错误。前者可以在任何时候出现,程序很少有关于如何恢复的合理想法,后者是一种需要预测和处理的错误情况

Java在实现时明确了这一区别;如果任何异常未被处理或声明为方法的潜在异常出口,则这是一个错误,但是从
RuntimeException
派生出来的任何异常都隐式正常

如果您的程序被适当地划分,并且用例允许这样做,那么您可以捕获某些运行时异常并关闭异常产生的分区,但这仅在特殊情况下有用

虽然这仅在Java中有效实施,但这一概念也可以在这里应用:

  • 解析输入数据失败是一个很容易处理的异常,因为抛出异常时程序处于哪个状态是很清楚的,所以清理很容易(继续下一个输入)
  • 从内存不足的情况中恢复比较困难,因为如果在写入时发生错误,则可能需要删除输出文件,否则将导致部分数据
  • 如果您的程序访问了无效内存,您不应该尝试恢复,因为您可能已经覆盖了其他内容(毕竟,您的程序显然不知道其数据在哪里),并且无法保证它将继续正常工作

我听过关于不处理您不知道如何处理的异常的引述。这是我听到的关于异常处理的最好建议。如果你不介意语言障碍,《例外C++》解释了我们可以给图书馆用户提供我们设计的类和如何恢复程序状态的保证(基本的、强的、现在扔的)。Christoper -关于引用的最好部分是它是跨语言和跨平台的。你用什么语言都没关系。如果语言支持抛出和处理异常,您仍然应该遵循相同的“除非您知道如何处理否则不要处理”方法。这是异常的一个很好的座右铭,但并不能真正回答OPs问题。列出th中定义的从不捕获异常完全不是理论上的