第5章 异常处理 王德俊 上海交通大学继续教育学院
第5章 异常处理 5.1 异常处理模型 5.2 .NET的Exception层次、属性 5.3 异常的抛出及用户自定义异常
5.2 .NET的Exception层次、属性 5.2.1 .NET的Exception层次 5.2.2 Exception常用属性
5.2.1 .NET的Exception层次 异常处理机制只允许引发和捕捉Exception类的对象及其派生类的对象 命名空间System的Exception类是.NET框架异常层次结构中的基类, Exception类派生的两个最重要的类是ApplicationException和 SystemException类: ApplicationException是一个基类,程序员可以由此创建专用于应用程序 的异常数据类型 程序执行期间,CLR可以在任何位置生成SystemException,大多数此类异 常都可以通过正确编码来避免,此类异常称为运行时异常,而且它们是从 SystemExcetion类派生而来的,如: IndexOutOfRangeException、 NullReferenceException、FormatException、DivideByZeroException等
5.2.1 .NET的Exception层次 如何判断程序会引发异常? 对于.NET框架类中的方法,可以查看MSDN文档,如果一个方法引发 了异常,其描述中就有“Exception”相关主题的内容,其中指定了 方法所引发的异常的类型,并简要描述了引发异常的原因
5.2.2 Exception常用属性 异常处理类型从Exception派生而来,该类的属性常用于阐明 捕捉到的异常的错误消息,其中两个重要的属性是Message和 StackTrace: Message属性保存与异常对象相关的错误消息,可以是异常类型相关 的默认消息,可以是自定义消息 StackTrace属性中包含一个代表方法调用堆栈的字符串,字符串代表 了异常发生时未结束处理的各个方法的顺序列表。
5.3 异常的抛出及自定义异常 在被调用代码中难以决定如何处理捕获的异常,这时可将捕 获的异常向调用代码抛出,由调用代码捕获后处理。 用户可以通过继承已有的相关异常类来定义新的、满足特定 需要的异常类。
5.3 异常的抛出及自定义异常 5.3.1 抛出异常 5.3.2 用户自定义异常
抛出异常有两种方式: 5.3.1 抛出异常 一种是直接抛出捕获的异常,格式如下: throw e; //e为已捕获的异常的名称 5.3 异常的抛出及自定义异常 5.3.1 抛出异常 抛出异常有两种方式: 一种是直接抛出捕获的异常,格式如下: throw e; //e为已捕获的异常的名称 另一种是利用捕获的异常创建新的异常,抛出新建的异常。格式如下: throw new异常类名([参数列表]); 当然,也可以写成: 异常类名 异常对象名 = new 异常类名([参数列表]); throw异常对象名;
考虑下面有关抛出异常的ThrowException程序: 5.3 异常的抛出及自定义异常 5.3.1 抛出异常(续) 【例5.3】 抛出异常的例子。 考虑下面有关抛出异常的ThrowException程序: class testException { int n, m; public void g() n = 10; m = 10; try n = 1 / (n - m); } catch (Exception e) throw new Exception(“这是在方法g()产生的异常:” + e.Message, e); //创建异常重发 // throw e; //异常原样重发 在方法g()中捕获一个零除异常,并利用该异常的Message属性值以及该异常本身作为参数来创建一个新的异常并将之抛出
很多情况下,程序员都可以利用.NET框架中现有的异常类来指 出程序中发生的异常,但有时可能希望为程序中发生的问题创 建更加具体的异常类型 5.3 异常的抛出及自定义异常 5.3.2 用户自定义异常 很多情况下,程序员都可以利用.NET框架中现有的异常类来指 出程序中发生的异常,但有时可能希望为程序中发生的问题创 建更加具体的异常类型 可以根据需要自定义异常类,但定义的异常类必须继承已有的 异常类,直接或间接从System命名空间的ApplicationException 派生而来
5.3 异常的抛出及自定义异常 5.3.2 用户自定义异常 Microsoft声称,用户自定义异常应该从 ApplicationException类派生而来,且应该有一个结尾为 Exception的类名,并需要定义3个构造函数: 一个默认构造函数; 一个接收字符串参数(错误消息)的构造函数; 一个接收字符串参数和异常参数(错误消息和内部异常对象) 的构造函数
class UserException : ApplicationException //定义用户的异常类 { 5.3 异常的抛出及自定义异常 5.3.2 用户自定义异常 关键代码如下: class UserException : ApplicationException //定义用户的异常类 { //重载Exception类的构造函数 public UserException() { } public UserException(string ms):base(ms) { } public UserException(string ms,Exception inner) : base(ms,inner) { } }
【例5.4】创建控制台应用程序MyExceptionClass,定义和使用 用户自定义异常。 要求: 5.3 异常的抛出及自定义异常 5.3.2 用户自定义异常(续) 【例5.4】创建控制台应用程序MyExceptionClass,定义和使用 用户自定义异常。 要求: 定义了一个学生类——student类 该类包含两个私有变量成员:name和score,分别表示学生姓名和 成绩,且name的长度不超过8个字节,score的范围为[0,100]; 包含一个方法成员f(),用于设置name和score。 自定义一个异常类UserException,当对name所赋的值的长度超过8个 字节或者对score所赋的值不在[0,100]范围内时都抛出此自定义异常。
private string name; //姓名,长度不超过8个字节 5.3 异常的抛出及自定义异常 5.3.2 用户自定义异常(续) class student //定义学生类 { private string name; //姓名,长度不超过8个字节 private double score; //成绩,范围为[0,100] public void setInfo(string name, double score) if (name.Length > 8) throw (new UserException("姓名长度超过了8个字节!")); } if (score < 0 || score > 100) throw (new UserException("非法的分数!")); this.name = name; this.score = score;
5.3 异常的抛出及自定义异常 5.3.2 用户自定义异常(续) static void Main(string[] args) { student s = new student(); try s.setInfo("张三", 958.5); } catch (Exception e) Console.WriteLine("产生异常:{0}", e.Message); Console.ReadKey();
在运行过程中由于试图对score赋值958.5,结果导致下列异常被创建和抛出: 5.3 异常的抛出及自定义异常 5.3.2 用户自定义异常(续) 执行该程序 : 在运行过程中由于试图对score赋值958.5,结果导致下列异常被创建和抛出: new UserException("非法的分数!")