Welcome

首页 / 软件开发 / C# / C#中如何处理异常

C#中如何处理异常2007-09-17 本站 throw语句

在学习如何处理异常之前,我们先介绍一下throw语句。

throw语句抛出一个异常:

throw expression

带有表达式的throw语句抛出的异常是在计算这个表达式时产生的。这个表达式必须表示一个System.Exception类型或它的派生类型的值。如果对表达式的计算产生的结果是null,则抛出的将是一个NullReferenceException异常。

不带表达式的throw语句我们稍后再介绍。

异常处理语句

异常是由try语句来处理的。

try语句提供了一种机制来捕捉块执行过程中发生的异常。以下是它的三种可能的形式:

●try-catch(s)
●try-finally
●try-catch(s)-finally

在介绍try语句之前,我们先介绍一个重要的概念:异常传播。当一个异常被抛出以后,程序将控制权转移给try语句中第一个能够处理该异常的catch子句。这个从异常抛出到控制转移给合适的异常处理语句的过程就叫做异常传播。

异常传播包括重复执行以下步骤,直到找到一个与该异常相匹配的catch子句。

(1).由里层到外层的执行每一个包围抛出点(异常被抛出的最初位置)的try语句。

●如果当前的try块包含一或多条catch子句,那么将按照这些子句的出现顺序对它们逐一检查以定位适合该异常的处理。所谓适合该异常的处理也就是第一个定义了该异常类型或其基类型的catch语句,异常传播也就结束了,程序控制转移到该catch语句执行。

●否则,如果当前的try块含有finally块的话,就执行finally块。如果该块又抛出一个异常,则当前处理的异常被终止。如果没有,则当finally块执行完成以后,再继续异常的处理。

(2).如果当前的成员函数调用中没有定位异常处理,则调用终止。并且在该成员函数调用点将该异常抛给调用者,重复执行上一步。

(3).如果该异常终止了当前线程或进程的所有成员函数调用,则说明该线程或进程中不存在对异常的处理,它将自行终止。

下面让我们回到try语句

如果catch语句中指定了一个类类型,则它必须是System.Exception类型或它的派生类型。如果同时指定了类类型和标识符,就是声明了一个异常变量。异常变量相当于一个作用范围为整个catch块的局部变量。在catch块的执行过程中,异常变量描述了当前正在处理的异常。如果想引用异常对象(其中包括很多重要的错误信息),就必须定义异常变量。

在一个catch块中,可以用不含表达式的throw语句将该catch块捕捉到的异常再次抛出,对于异常变量的分配不会改变两次抛出的异常。

既没有定义异常类型也没有定义异常变量的catch子句称做一般catch子句。该catch子句一般在事先不能确定会发生什么样的异常的情况下使用。一个try语句中只能有一个一般catch子句,而且如果有的话,该catch子句必须排在其它catch子句的后面。

尽管throw语句(含表达式)只能抛出System.Exception类型或它的派生类型的异常,但其它语句并不受该规则限制,因而可以抛出其它类型的异常。比如用一般catch语句就可以捕捉这一类异常,然后利用一个不含表达式的throw语句就可将其再次抛出。

由于寻求异常的处理是通过按照catch子句出现的顺序逐一检查catch子句,因此如果有一个catch子句定义的异常类型与比它先出现的catch子句定义的类型相同或是它的派生类型,就会发生错误。下面的例子中我们演示了try-catch语句的使用以及再次抛出异常。

程序清单8-9:

using System;class Test{static void F(){ try{ G(); } catch(Exception e){ Console.WriteLine("Exception in F:"+e.Message); e=new Exception("F"); throw; }} static void G(){ throw new Exception("G");} static void Main(){ try{ F(); } catch(Exception){ Console.WriteLine("Exception in Main:"+e.Message); }}}
F方法捕捉到了一个异常,向控制台写了一些诊断信息,改变异常变量的内容,然后将该异常再次抛出。这个被再次抛出的异常与最初捕捉到的异常是同一个。因此程序的输出结果如下:

Exception in F:G

Exception in Main:G