? 异常是程序中的运行时错误,它违反了系统约束或应用程序约束,或是正常操作时不会发生的状况。如果程序没有提供处理异常的代码,系统会挂起这个程序。例如,下面的代码在试图用 0 除一个数时抛出一个异常:
? 在没有异常处理程序的情况下,应用程序将停止(或者崩溃),并向用户显示非常不友好的错误消息。异常处理的目标是通过以下操作来响应异常:
? try 语句用来指明为避免出现异常而被保护的代码段,并在发生异常时提供代码处理。其包含 3 个部分组成:
处理异常
? 将上述代码段放在一个 try 块中,并提供一个简单的 catch 子句来捕获并处理异常。
? BCL 定义了许多异常类,每一个类代表一种指定的异常类型。当一个异常发生时,CLR 创建该类型的异常对象并寻找适当的 catch 子句以处理它。
? 所有异常类都派生自 System.Exception 类,System.Exception 类派生自 System.Object 类。
? 异常对象含有只读属性,该属性提供有助于调试应用程序的异常信息。
? catch 子句处理异常,有如下 4 种形式:
? 形式 4 的 catch 子句是在 C# 6.0 中添加的,相较于形式 3,异常对象还需满足特定条件,该条件被称为过滤器。这允许程序员编写更小、更专一的异常处理程序,而无需再单个处理程序中包含大量 if 语句。
? 有关 when 子句的重要特征如下:
? catch 子句段可以包含多个 catch 子句。
? 当发生异常时,系统按顺序搜索 catch 子句的列表,第一个匹配该异常对象类型的 catch 子句被执行。
? 如果程序的控制流进入了带 finally 块的 try 语句,那么 finally 始终会被执行。
? 即是 try 块中有 return 语句,或在 catch 块中抛出一个异常,finally 块也总是会在返回到调用代码之前执行。
? 上述代码在 inVal 值为 5 时也会打印 finally 块中的语句。
? 当程序抛出异常时,系统查看该程序是否提供了异常处理程序,具体流程如下:
? 如果异常在一个没有被 try 语句保护的代码段抛出,或者如果 try 语句没有匹配的异常处理程序,系统将不得不进一步寻找匹配的处理程序。即,按顺序搜索调用栈,查看是否存在带匹配的处理程序的封装 try 块。
? 如果异常发生在 Method2 内的 try 块内部,系统会执行如下操作:
? 使用 throw 语句使代码显示抛出异常,throw 语句的语法如下:
? 下面的代码在 try 块中进行参数 null 检查,创建并抛出 ArgumentNullException 异常。该实例在 catch 语句中被捕获,错误被打印出来。
? throw 语句可以在 catch 块内部不带异常对象使用。
? 代码中有些地方不允许使用语句,而只能使用表达式。C# 7.0 后,可以在只能应用表达式的地方使用 throw 表达式,其语法和 throw 语句相同。