异常处理的指导原则

只捕捉你能处理的异常
  通常,一些类型的异常可以处理,但是另一些类型的异常不能处理。例如,试图打开一个正在使用的文件来进行独占式的读/写访问,会引发一个System.IO.IOException,因为文件已经在使用了。通过捕捉这种类型的异常,代码可以向用户报告该文件正在使用,并允许用户选择取消或者重试。只有那些已知对车的异常才应捕捉。其他异常类型应该留在栈中较高的调用者去处理。

不要隐藏你不能完全处理的异常
  新手程序员常犯的一个错误是捕捉所有的异常,然后假装什么都没有发生,而不向用户报告未处理的异常。这有可能导致严重的系统问题逃过检测。除非代码采取现实的行动来处理一个异常,或者显示的确定一个异常无害,否则catch块应当重新引发异常,而不是在捕捉了之后在调用者面前隐藏他们。尤其要注意的是catch(System.Exception)和常规catch块应放在调用栈中较高的位置,除非你决定在块中重新引发异常

尽可能的少使用System.Exception和常规Catch块
  几乎所有的异常都是从System.Exception派生的。然而,处某些System.Exception的最佳方式是不对它们进行处理,或者尽快以正常的方式关闭程序。例如,想System.OutOfMemoryException这样的异常是无法恢复的,所以最佳对策就是关闭应用程序。相应的catch块只应运行清理或紧急代码(比如保存任何易失的数据),然后马上关闭相应的应用程序或者使用throw;语句重新引发异常。

避免在调用栈较低的位置报告或记录异常
  新手程序员倾向于异常一发生就记录它,或者向用户报告它。然而,由于当前正处在调用栈中较低的位置,而这些位置很少能够完整的处理异常,所以会重新引发异常。像这样的catch块不应该记录异常,也不应该向用户报告。假如异常被巨鹿,然后又被重新引发(调用栈中较高的调用者可能做同样的事),就会造成重复出现的异常记录项。更糟的是,向用户显示异常可能并不匹配应用程序。例如,在一个windows应用程序中,使用System.COnsole.WriteLine(),用户永远看不到显示的内容。类似的,在无人值守的命令行进程中显示一个对话框,可能根本就不会被别人看到,而且可能使应用程序冻结在这个位置。与日志记录和异常有关的用户界面应该保留到调用栈中较高的位置。

在一个Catch块中可以使用throw;而不是throw <异常语句>语句
  可以在一个catch块中重新引发异常。例如,在catch(ArgumenhtNullException exception)的实现中,可以包含对throw exception的调用。然而重新引发异常,会将栈追踪重置为重新引发的位置,而不是原始引发的位置。所以,假设如果不是要重新引发一个不同类型的异常,或者不是要故意隐藏原始调用栈,就应该使用throw ; 语句,允许相同的异常在调用栈中向上传播。

重新引发不同的异常是要小心
  在一个catch块的内部,假如你重新引发一个不同的异常,那么不仅会重置引发点,还会隐藏原始异常。为了保留原始异常,需要重新设置新异常的InnerException属性(该属性通常可以通过构造器来赋值)。通常只应在以下情况下才重新引发一个不同的异常
  a)更改异常类型可以更好的澄清问题
    例如,在对Logon(User user)的一个调用中,假如遇到用户列表文件不能访问的情况,那么重新引发一个不同的异常类型,要比引发System.IO.IOException更合适。
  b)私有数据是原始异常的一部分
    在上面的例子中,假如文件路径包含在原始的System.IO.IOExceptionzhong ,就会暴露敏感的系统信息,所以应该使用其他异常类型来封装它(当然,前提是原始异常没有设置InnerException属性)。
  c)异常类型过于具体,以至于调用者不能恰当的处理
    例如,不要引发特定于某个数据库系统的异常。相反,可以使用一个较为广泛的异常,以避免在调用栈比较高的位置写特定于某个数据库的代码

原文地址:https://www.cnblogs.com/changweihua/p/2005427.html