《C#异常处理1.ppt》由会员分享,可在线阅读,更多相关《C#异常处理1.ppt(26页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、 C#异常处理异常处理 吴江洲吴江洲2013.12.85.1 一个产生异常的简单程序一个产生异常的简单程序5.2 异常的捕获与处理异常的捕获与处理5.3 异常的抛出及自定义异常异常的抛出及自定义异常本本 章章 内内 容容5.1 一个产生异常的简单程序创建控制台应用程序创建控制台应用程序ExceptionPro,该程序能够捕获产生的,该程序能够捕获产生的异常,并进行相应的处理:异常,并进行相应的处理:static void Main(string args)int n,m;string s=Console.ReadLine();n=0;try m=Convert.ToInt16(s);/产生异常
2、的语句产生异常的语句 Console.WriteLine(m=0,m);catch(Exception e)/捕获异常捕获异常 Console.WriteLine(产生异常:产生异常:0,e.Message);/处理异常处理异常 Console.ReadKey();试图将试图将“123ab4”转换转换为整数时产生了为整数时产生了异常异常产生该异常时自动产生该异常时自动转向执行该语句转向执行该语句 5.1 一个产生异常的简单程序说明:说明:p可能出现异常的代码放在可能出现异常的代码放在try块中块中p处理异常的代码则放在处理异常的代码则放在catch块中块中当当程程序序在在运运行行过过程程中中产
3、产生生异异常常时时,则则会会转转向向执执行行catch块块中中的的代代码码,从从而而避避免免因因异异常常的的产产生生而而导导致致程序运行的非正常终止。程序运行的非正常终止。作用:作用:使程序具有较强的错误处理能力,使得程序更加使程序具有较强的错误处理能力,使得程序更加健壮和稳定。健壮和稳定。5.2 异常的捕获与处理5.2.1 异常的概念异常的概念u所谓所谓异常异常,它是指程序在运行过程(而非编译,它是指程序在运行过程(而非编译过程)中产生的错误过程)中产生的错误u编译过程中的错误可以通过代码调试来避免,编译过程中的错误可以通过代码调试来避免,异常一般是不能避免的(只能是减少)异常一般是不能避免
4、的(只能是减少)5.2 异常的捕获与处理5.2.2 try-catch结构结构try-catch结构:结构:try /可能产生异常的代码可能产生异常的代码catch(异常类异常类 对象名对象名)/处理异常的代码处理异常的代码说明:说明:(1)一旦在)一旦在try块中有某一条语句执行时产生异常,块中有某一条语句执行时产生异常,程序立即转向执行程序立即转向执行catch块中的代码,而不会再块中的代码,而不会再执行该语句后面的其他语句。执行该语句后面的其他语句。当然,如果当然,如果try块中的语句都不产生异常,那么就块中的语句都不产生异常,那么就不会有任何的不会有任何的catch块被执行块被执行。说
5、明:说明:(2)“(异常类异常类 对象名对象名)”部分可以省略。如果省略部分可以省略。如果省略这部分,则不管在这部分,则不管在try块中产生什么异常,程序块中产生什么异常,程序都会转向执行都会转向执行catch块中的代码,但在这种情况块中的代码,但在这种情况下我们无法获取此异常的任何信息。下我们无法获取此异常的任何信息。说明:说明:(3)“异常类异常类”用于决定要捕获的异常的类型,不用于决定要捕获的异常的类型,不同的异常类能捕获和处理不同的异常,常用的同的异常类能捕获和处理不同的异常,常用的异常类如表异常类如表5.1所示所示 5.2 异常的捕获与处理5.2.2 try-catch结构结构【例例
6、5.1】内存溢出异常的捕获和处理。内存溢出异常的捕获和处理。在申请较大块的存储空间时可能出现失败,这在申请较大块的存储空间时可能出现失败,这时会产生一个内存溢出的异常时会产生一个内存溢出的异常(OutOfMemoryException),根据这个异常我们就),根据这个异常我们就可以决定下一步要采取什么样的动作。可以决定下一步要采取什么样的动作。在下面的在下面的OutOfMemExc_Exa程序中,申请了程序中,申请了20000*30000个存储单元,结果超出了笔者机器的个存储单元,结果超出了笔者机器的可用内存空间,因而产生了内存溢出异常。可用内存空间,因而产生了内存溢出异常。5.2 异常的捕获
7、与处理5.2.2 try-catch结构结构【例例5.1】内存溢出异常的捕获和处理。内存溢出异常的捕获和处理。static void Main(string args)try int,a=new int20000,30000;/申请存储空间申请存储空间 catch(OutOfMemoryException e)/异常捕获与处理异常捕获与处理 Console.WriteLine(产生异常:产生异常:0,e.Message);Console.ReadKey();5.2 异常的捕获与处理5.2.3 try-catch-catch结构结构当当出出现现的的多多个个不不同同的的异异常常,需需要要用用到到带
8、带多多个个catch块的块的try-catch-catch结构。结构。【例例5.2】多个异常的捕获和处理。多个异常的捕获和处理。程程序序中中,try结结构构包包含含的的两两条条语语句句在在执执行行时时都都会会产产生生异异常常,分分别别为为DivideByZeroException异异常常和和OutOfMemoryException异异常常。这这两两个个异异常常分分别别由两个由两个catch结构来捕获和处理。结构来捕获和处理。5.2 异常的捕获与处理5.2.3 try-catch-catch结构结构 static void Main(string args)int n,m;n=30000;m=3
9、0000;try n=1/(n-m);int,a=new intn,n;catch(OutOfMemoryException e1)Console.WriteLine(内存溢出异常:内存溢出异常:0,e1.Message);catch(DivideByZeroException e2)Console.WriteLine(零除异常:零除异常:0,e2.Message);由于由于DivideByZeroException异常异常先发生,故转向执行第二个先发生,故转向执行第二个catch块,第一个块,第一个catch块没有被执行。块没有被执行。5.2 异常的捕获与处理5.2.3 try-catch-
10、catch结构结构多个多个catch块在出现顺序上有何要求呢?这要分两种情况来讨论:块在出现顺序上有何要求呢?这要分两种情况来讨论:(1)catch后后 面面 的的 异异 常常 类类 之之 间间 没没 有有 继继 承承 关关 系系(如如DivideByZeroException和和 System.OutOfMemoryException),这这时时catch块块的的位位置置不不分分先先后后,即即在在前前、在在后后都都不不影影响响程程序序的的运运行结果。例如,上例中的行结果。例如,上例中的catch结构就属于这种情况。结构就属于这种情况。(2)catch后后 面面 的的 异异 常常 类类 之之
11、间间 存存 在在 继继 承承 关关 系系(如如DivideByZeroException类类继继承承了了ArithmeticException类类、所所有有异异常常类类都都继继承承了了Exception类类),这这时时派派生生类类所所在在的的catch块块必必须须放放在在基基类类所所在在的的catch块块的的前前面面。即即作作用用范范围围小小的的catch块块放放在在前前面,作用范围大的块放在后面面,作用范围大的块放在后面。5.2 异常的捕获与处理5.2.3 try-catch-catch结构结构例例如如,下下面面代代码码中中的的两两个个catch块块的的顺顺序序是是不不能能颠颠倒倒的的,否否
12、则则无无法通过编译检查:法通过编译检查:int n=1,m=1;try n=1/(n-m);catch(DivideByZeroException e)/派生类所在的派生类所在的catch块块(作用范围小)(作用范围小)Console.WriteLine(产生异常:产生异常:0,e.Message);catch(ArithmeticException ee)/基类所在基类所在catch块块(作用范围大)(作用范围大)Console.WriteLine(产生异常:产生异常:0,ee.Message);5.2 异常的捕获与处理5.2.3 try-catch-catch结构结构由于由于Excepti
13、on类是所有其他异常类的基类,因此类是所有其他异常类的基类,因此Exception类所在的类所在的catch块必须是最后面的块必须是最后面的catch块,它可以捕获任意类型的异常。块,它可以捕获任意类型的异常。显然,如果不想具体区分是哪一种类型的异常,显然,如果不想具体区分是哪一种类型的异常,也不想利用也不想利用Exception派生类更强大、更具针对性派生类更强大、更具针对性的处理能力,我们可以利用的处理能力,我们可以利用Exception类类“笼统笼统”地捕获所有的异常。这使代码变得简洁,保证所地捕获所有的异常。这使代码变得简洁,保证所有的异常都能被捕获,而不会出现遗漏。有的异常都能被捕获
14、,而不会出现遗漏。5.2 异常的捕获与处理5.2.4 try-catch-finally结构结构为什么要用为什么要用finally块?块?程程序序在在运运行行过过程程中中一一旦旦出出现现异异常常会会立立即即转转向向执执行行相相应应catch块块中中的的语语句句,执执行行完完后后接接着着执执行行try-catch结结构构后后面面的的语语句句。这这意意味味着着在在出出现现异异常常时时程程序序并并不不是是按按照照既既定定的的顺顺序序执执行行,而是跳转执行。而是跳转执行。为为维维持持系系统统的的有有效效性性和和稳稳定定性性,必必须须保保证证有有相相应应的的代代码码能能够够“弥弥补补”被被跨跨越越代代码
15、码的的工工作作,主主要要是是完完成成必必要要的的清清理理工工作作(如如关关闭闭文文件件、释释放放内内存存等等)。这这种种保保证证机机制制可可以以由由带带finally的的try-catch-finally结构来实现。结构来实现。5.2 异常的捕获与处理5.2.4 try-catch-finally结构结构try-catch-finally结构的格式如下:结构的格式如下:try /可能产生异常的代码可能产生异常的代码catch(异常类异常类 对象名对象名)/处理异常的代码处理异常的代码finally /完成清理工作的代码完成清理工作的代码说明:说明:u根据需要,可以在这种结构根据需要,可以在这种
16、结构中带中带1个或多个个或多个catch块。块。u不管在不管在try块中是否产生异常,块中是否产生异常,finally块中的代码都会被执块中的代码都会被执行。也就是说,行。也就是说,不管不管catch块块是否被执行,是否被执行,finally块都会块都会被执行被执行。哪怕是在执行。哪怕是在执行catch块中遇到块中遇到return语句,也会语句,也会执行执行finally块中的语句。块中的语句。5.2 异常的捕获与处理5.2.4 try-catch-finally结构结构例如:例如:int n=1,m=1;try n=1/(n-m);catch(Exception e)Console.Writ
17、eLine(产生异常:产生异常:0,e.Message);return;Console.WriteLine(紧跟在紧跟在return后面后面.);finally Console.WriteLine(finally块块.);Console.WriteLine(try-catch-finally结构后面的部分结构后面的部分.);产生零除异常产生零除异常执行执行catch块块遇到遇到return语句语句该语句不被执行该语句不被执行该语句被执行该语句被执行该语句不被执行,因在该语句不被执行,因在catch块中遇到块中遇到return语句语句 可以看到,虽然可以看到,虽然catch块包含了块包含了一条一
18、条return语句,且执行该语句,且执行该return语句时也会立即结束当前语句时也会立即结束当前函数的执行,但在结束之前仍然函数的执行,但在结束之前仍然会执行会执行finally块。这说明,块。这说明,只要只要程序进入程序进入try-catch-finally结构,结构,都会执行都会执行finally块。块。5.3 异常的抛出及自定义异常一般来说,异常在被捕获后应进行相应的处理。但是有的一般来说,异常在被捕获后应进行相应的处理。但是有的代码是为其他代码提供调用服务的,在这种代码中可能难代码是为其他代码提供调用服务的,在这种代码中可能难以决定应该对捕获的异常进行何种处理,这时最好将捕获以决定应
19、该对捕获的异常进行何种处理,这时最好将捕获的异常向调用代码抛出,由调用代码捕获后再进行相应的的异常向调用代码抛出,由调用代码捕获后再进行相应的处理。处理。抛出异常有两种方式:一种是将捕获的异常原封不动地直抛出异常有两种方式:一种是将捕获的异常原封不动地直接抛出;另一种是先利用捕获的异常来创建新的异常(在接抛出;另一种是先利用捕获的异常来创建新的异常(在创建过程中可以进行一些必要的处理),然后将新建的异创建过程中可以进行一些必要的处理),然后将新建的异常抛出。常抛出。除了系统提供的异常类以外,用户也可以通过继承已有的除了系统提供的异常类以外,用户也可以通过继承已有的相关异常类来定义新的、满足特定
20、需要的异常类,这就是相关异常类来定义新的、满足特定需要的异常类,这就是用户自定义异常。用户自定义异常。5.3 异常的抛出及自定义异常5.3.1 抛出异常抛出异常抛出异常有两种方式。一种是直接抛出,也称为异常重发,抛出异常有两种方式。一种是直接抛出,也称为异常重发,格式如下:格式如下:throw e;/e为已捕获的异常的名称为已捕获的异常的名称另一种是先利用捕获的异常来创建新的异常,然后将之抛另一种是先利用捕获的异常来创建新的异常,然后将之抛出,格式如下:出,格式如下:throw new异常类名异常类名(参数列表参数列表);当然,也可以写成:当然,也可以写成:异常类名异常类名 异常对象名异常对象
21、名=new 异常类名异常类名(参数列表参数列表);throw异常对象名异常对象名;5.3 异常的抛出及自定义异常5.3.1 抛出异常抛出异常【例例5.3】抛出异常的例子。抛出异常的例子。考虑下面有关抛出异常的考虑下面有关抛出异常的ThrowtException程序:程序: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;/异常重发异常重发 在
22、方法在方法g()中捕获一个零除异常,中捕获一个零除异常,并利用该异常的并利用该异常的Message属性值属性值以及该异常本身作为参数来创建以及该异常本身作为参数来创建一个新的异常并将之抛出一个新的异常并将之抛出 5.3 异常的抛出及自定义异常5.3.1 抛出异常抛出异常这种抛出方法的优点是,程序员可以利用捕获到的异常的相关信这种抛出方法的优点是,程序员可以利用捕获到的异常的相关信息构造满足调用者需要的新异常,同时也可以将原异常息构造满足调用者需要的新异常,同时也可以将原异常“嵌入嵌入”到新的异常中而被同时抛出。如果用下列语句对异常进行重发,到新的异常中而被同时抛出。如果用下列语句对异常进行重发
23、,则程序员不能对要抛出的异常进行任何的修改(只能原样抛出):则程序员不能对要抛出的异常进行任何的修改(只能原样抛出):throw e;/异常重发异常重发而且由于抛出的是最初的异常,故其而且由于抛出的是最初的异常,故其InnerException属性值为属性值为null,这会,这会导致下列语句出现错误:导致下列语句出现错误:Console.WriteLine(内部的异常(原异常):内部的异常(原异常):+ex.InnerException.Message);5.3 异常的抛出及自定义异常5.3.2 用户自定义异常用户自定义异常系统提供的异常类也许不能很好地满足我们的需要,这时程序员系统提供的异常
24、类也许不能很好地满足我们的需要,这时程序员可以根据需要定义自己的异常类,但定义的异常类必须继承已有可以根据需要定义自己的异常类,但定义的异常类必须继承已有的异常类。的异常类。【例例5.4】定义和使用用户自定义异常。定义和使用用户自定义异常。设计思想:在程序设计思想:在程序MyExceptionClass中先定义了一个学生类中先定义了一个学生类student类,该类包含两个私有变量成员:类,该类包含两个私有变量成员:name和和score,分别表,分别表示学生姓名和成绩,且示学生姓名和成绩,且name的长度不超过的长度不超过8个字节,个字节,score的范围的范围为为0,100;另外还包含一个方
25、法成员;另外还包含一个方法成员f(),用于设置,用于设置name和和score。然后自定义一个异常类然后自定义一个异常类UserException,当对,当对name所赋的值的长所赋的值的长度超过度超过8个字节或者对个字节或者对score所赋的值不在所赋的值不在0,100范围内时都抛出范围内时都抛出此自定义异常。关键代码如下:此自定义异常。关键代码如下:5.3 异常的抛出及自定义异常5.3.2 用户自定义异常用户自定义异常关键代码如下:关键代码如下:class UserException:Exception /定义用户的异常类定义用户的异常类 /重载重载Exception类的构造函数类的构造函
26、数 public UserException()public UserException(string ms):base(ms)public UserException(string ms,Exception inner):base(ms,inner)5.3 异常的抛出及自定义异常5.3.2 用户自定义异常用户自定义异常 class student/定义学生类定义学生类 private string name;/姓名,长度不超过姓名,长度不超过8个字节个字节 private double score;/成绩,范围为成绩,范围为0,100 public void setInfo(string n
27、ame,double score)if(name.Length 8)throw(new UserException(姓名长度超过了姓名长度超过了8个字节!个字节!);if(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();5.3 异常的抛出及自定义异常5.3.2 用户自定义异常用户自定义异常执行该程序执行该程序:在运行过程中由于试图对在运行过程中由于试图对score赋值赋值958.5,结果导致下列异常被创建和,结果导致下列异常被创建和抛出:抛出:new UserException(非法的分数!非法的分数!)