异常处理课件_第1页
异常处理课件_第2页
异常处理课件_第3页
异常处理课件_第4页
异常处理课件_第5页
已阅读5页,还剩112页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

11异常处理异常处理11异常处理1、.NETFramework中的异常异常是正在执行的程序所遇到的任何错误情况或意外行为。下面这些情况都可引发异常:应用程序代码或其调用的代码(如共享库)中有错误;操作系统资源不可用;公共语言运行时遇到意外情况(如无法验证代码)等等。11异常处理在.NETFramework中,异常是从System.Exception类继承的对象。异常从发生问题的代码区域引发,然后沿堆栈向上传递,直到应用程序处理它或程序终止。1、.NETFramework中的异常11异常处理1.1异常处理与传统的错误处理方法传统上,语言的错误处理模型有两种:语言采用自己独特的方式来检测错误并定位错误处理程序;依赖于操作系统提供的错误处理机制。运行时异常处理具有以下特点:处理异常时不用考虑该异常的生成或处理语言;异常处理时不要求任何特定的语言语法,而是允许每种语言定义自己的语法;允许跨进程甚至跨计算机边界引发异常。11异常处理

与其他错误通知方法相比,异常具有以下优点:不再有出现错误而不被人注意的情况;无效值不会继续在系统中传播;不必检查返回代码;可以轻松添加异常处理代码,以增加程序的可靠性;运行时的异常处理比基于Windows的C++错误处理更快。由于执行线程例行地遍历托管代码块和非托管代码块,因此运行时可以抛出或捕获托管或非托管代码中的异常。非托管代码可以同时包含C++样式的SEH异常和基于COM的HRESULT。1.1异常处理与传统的错误处理方法11异常处理1.2运行时如何管理异常运行时的异常处理模型是基于异常对象和受保护代码块。出现异常时,创建一个Exception对象来表示该异常。运行时为每个可执行文件创建一个异常信息表。在异常信息表中,可执行文件的每个方法都有一个关联的异常处理信息数组(可以为空)。数组中的每一项描述一个受保护的代码块、任何与该代码关联的异常筛选器和任何异常处理程序(catch语句)。此异常表非常有效,仅在异常发生时使用资源;在没有异常发生时,它不会引起处理器时间或内存使用方面的任何性能损失。11异常处理

异常信息表为受保护代码块提供了四种类型的异常处理程序:finally处理程序,每当“块”退出时它都会执行,不考虑退出是由正常控制流引起的还是由未经处理的异常引起。错误处理程序,在异常发生时一定执行,但在正常控制流完成时不执行。类型筛选的处理程序,它处理指定类或其派生类的任何异常。用户筛选的处理程序,它运行用户指定的代码,来确定异常应由关联的处理程序处理还是应传递给下一个受保护的块。每种语言根据自己的规范实现这些异常处理程序。1.2运行时如何管理异常11异常处理

异常发生时,运行时分两步来处理:运行时在数组中搜索执行下列操作的第一个受保护块:保护包含当前执行的指令的区域。包含异常处理程序或包含处理异常的筛选器。如果出现匹配项,则运行时会创建一个Exception对象来描述该异常。然后运行时执行位于该异常的发生语句和处理语句之间的所有finally语句或错误语句。异常处理程序的顺序很重要;最里面的异常处理程序最先计算。异常处理程序可以访问捕捉异常程序中的局部变量和本地内存,但异常发生时的任何中间值都会丢失。1.2运行时如何管理异常11异常处理1.3筛选运行时异常可以按类型或按某些用户定义的条件对捕捉和处理的异常进行筛选。类型筛选的处理程序管理特定类型异常或者是其派生类。如catch(e){Console.WriteLine("[Data]{0}",e);}用户筛选的异常处理程序根据用户为异常定义的要求来捕捉和处理异常。11异常处理

如果当前方法中没有出现匹配项,则运行时搜索当前方法的每一个调用方,并沿着堆栈一直向上查找。如果任何调用方都没有匹配项,则运行时允许调试器访问该异常。如果调试器不能附加到该异常,则运行时引发AppDomain.UnhandledException事件。如果没有该事件的侦听器,则运行时转储堆栈跟踪并结束应用程序。1.3筛选运行时异常11异常处理1.4处理异常的最佳做法设计良好的错误处理代码块集使程序更可靠并且不容易崩溃。下面列出关于异常处理最佳做法方面的建议:知道何时设置Try/Catch块。所选择的方法依赖于预计事件发生的频率。如果事件确实是异常的并且是一个错误(如意外的文件尾),则使用异常处理比较好,因为正常情况下执行的代码更少。如果事件是例行发生的,使用编程方法检查错误比较好。在此情况下,如果发生异常,将需要更长的时间处理。11异常处理

在可能生成异常的代码周围使用Try/Finally块,并将Catch语句集中在一个位置。以这种方式,Try语句生成异常,Finally语句关闭或释放资源,而Catch语句从中心位置处理异常。始终按从最特殊到最不特殊的顺序对Catch块中的异常排序。此方法将保证特殊异常在传递给更常规的Catch块之前被处理。以“Exception”这个词作为异常类名的结尾。例如:

publicclassMy:Exception{

}

1.4处理异常的最佳做法11异常处理

当创建用户定义的异常时,必须确保异常的元数据对远程执行的代码可用,包括当异常跨应用程序域发生时。例如,假设应用程序域A创建应用程序域B,后者执行引发异常代码。A若想正确捕获和处理异常,它必须能够找到包含B所引发的异常的程序集。如果包含B引发的异常的程序集位于B的应用程序基目录下,而不是位于A的应用程序基目录下,则A将无法找到异常,此时将引发异常。为避免此情况,可以两种方式部署包含异常信息的程序集:将程序集放在两个应用程序域共享的公共应用程序基中如果两个应用程序域不共享一个公共应用程序基,则用强名称给包含异常信息的程序集签名并将其部署到全局程序集缓存中。1.4处理异常的最佳做法11异常处理

在大多数情况下,使用预定义的异常类型。但是在程序中可以定义新异常类型。引入新异常类,使程序员能够根据异常的不同在代码中采取不同的操作。在C#和C++中创建自己的异常类时,至少使用三个公共构造函数。对于大多数应用程序,从Exception类派生自定义异常。在每个异常中都包含一个本地化描述字符串。当用户看到错误消息时,该消息从抛出异常的描述字符串派生,而不是从异常类派生。1.4处理异常的最佳做法11异常处理

使用语法上正确的错误消息。在异常的描述字符串中,每个句子都应以句号结尾。为编程访问提供Exception属性。仅当程序需要附加信息时,才在异常中包含附加信息(不包括描述字符串)。对极常见的错误情况返回null。例如,如果没找到文件,Open将返回null;但如果文件被锁定,则引发异常。类的设计应保证其在正常使用中不引发异常。例如,类提供一种确定是否已到达文件末尾的方法。这避免了在读取超过文件尾时引发的异常。见下例:1.4处理异常的最佳做法11异常处理

class{publicvoidReadAll(){if(==null){thrownewSystem.ArgumentNullException();}intb;//Setthestreampositiontothebeginningofthefile.(0,SeekOrigin.Begin);//Readeachbytetotheendofthefile.for(inti=0;i<;i++){b=();Console.Write(b.ToString());//Ordosomethingelsewiththebyte.}}}1.4处理异常的最佳做法11异常处理2、异常处理C#语言的异常处理功能:帮助程序员处理程序运行时出现的任何意外或异常情况。异常处理使用try、catch和finally关键字尝试某些可能失败的操作,以处理失败情况。公共语言运行时(CLR)、.NETFramework或任何第三方库或者应用程序代码都可以生成异常。异常可以使用throw关键字创建。11异常处理

很多情况下,异常可能不是由代码直接调用的方法引发,而是由所调用堆栈中位置更靠下的另一个方法所引发。在这种情况下,CLR将展开堆栈,查找是否有方法包含了针对该特定异常类型的catch块,如果找到这样的方法,就会执行找到的第一个这样的catch块。如果在调用堆栈中的任何位置都没有找到适当的catch块,就会终止该进程,并向用户显示一条消息。2、异常处理11异常处理

示例:使用一个方法检测是否有被零除的情况;如果有异常处理,则捕获该错误。如果没有异常处理,此程序将终止并产生“DivideByZeroException未处理”错误。2、异常处理11异常处理

classExceptionTest{staticdoubleSafeDivision(doublex,doubley){if(y==0)thrownewSystem.DivideByZeroException();returnx/y;}staticvoidMain(){//Inputfortestpurposes.Changevaluestoseeexceptionhandlingbehavior.doublea=98,b=0;doubleresult=0;

try{result=SafeDivision(a,b);Console.WriteLine("{0}dividedby{1}={2}",a,b,result);}catch(DivideByZeroExceptione){Console.WriteLine("Attempteddividebyzero.");}}}2、异常处理11异常处理异常概述各种类型的异常最终都是由System.Exception派生而来。在可能引发异常的语句周围使用try块。一旦try块中发生异常,控制流将跳转到第一个关联的异常处理程序(无论该处理程序存在于调用堆栈中的什么位置)。在C#中,catch关键字用于定义异常处理程序。11异常处理

如果给定异常没有异常处理程序,则程序将停止执行,并显示一条错误消息。除非可以处理某个异常并使应用程序处于已知状态,否则请不要捕捉该异常。如果catch块定义了一个异常变量,则可以用它获取有关所发生异常类型的更多信息。无论是否产生异常,finally块中的代码都会被执行。使用finally块释放资源,例如关闭在try块中打开的任何流或文件。异常概述11异常处理2.1异常处理语句C#为处理在程序执行期间可能出现的反常情况(称作异常)提供内置支持。这些异常由正常控制流之外的代码处理。throwtry-catchtry-finallytry-catch-finally不带有catch或finally块的try块将导致编译器错误。11异常处理2.2throwthrow语句用于抛出程序执行期间出现的异常情况。抛出的异常是一个对象,如classMyException:System.Exception{}//...thrownewMyException();通常,throw语句与try-catch或try-finally语句一起使用。11异常处理

publicclassThrowTest2{staticintGetNumber(intindex){int[]nums={300,600,900};if(index>nums.Length){thrownewIndexOutOfRangeException();}returnnums[index];}staticvoidMain(){intresult=GetNumber(3);}}/*Output:TheSystem.IndexOutOfRangeExceptionexceptionoccurs.*/2.2throw11异常处理如何显式引发异常可以使用throw语句显式抛出异常。可以使用throw语句再次抛出捕获的异常。较好的编码做法是,向再次抛出的异常添加信息以在调试时提供更多信息。下面的代码示例使用try/catch块捕获可能的。try块后面是catch块,catch块捕获,如果找不到数据文件,则向控制台写入消息。下一条语句是throw语句,该语句引发新的并向该异常添加文本信息。11异常处理

usingSystem;usingSystem.IO;publicclassProcessFile{publicstaticvoidMain(){fs=null;try{//Opensatexttile.fs=new(@"C:\temp\data.txt",);StreamReadersr=newStreamReader(fs);stringline;//Avalueisreadfromtheoutputtotheconsole.line=sr.ReadLine();Console.WriteLine(line);}如何:显式引发异常11异常处理catch(e){Console.WriteLine("[Data]{0}",e);thrownew(@"[data.txtnotinc:\tempdirectory]",e);}finally{if(fs!=null)fs.Close();}}}如何显式引发异常11异常处理2.3try-catchtry-catch语句由一个try块后跟一个或多个catch子句构成,这些子句指定不同的异常处理程序。引发异常时,公共语言运行时(CLR)会查找处理此异常的catch语句。如果当前执行的方法不包含这样的catch块,则CLR会查看调用当前方法的方法,然后会遍历调用堆栈。如果找不到catch块,则CLR会向用户显示一条有关未经处理的异常的消息并停止执行程序。11异常处理catch块catch块可以指定要捕捉的异常类型。类型规范称为“异常筛选器”。异常类型应从Exception派生出来。一般而言,不会将Exception指定为异常筛选器,除非知道如何处理try块中可能引发的所有异常,或者在catch块中包括了throw语句。虽然可以使用不带参数的catch子句捕捉任何类型的异常,但不推荐这种用法。通常,应该只捕捉那些知道如何从中恢复的异常。因此,应该总是指定一个从System.Exception派生的对象参数。11异常处理

例如:catch(InvalidCastExceptione){}在同一个try-catch语句中可以使用一个以上的特定catch子句;即具有不同异常筛选器的多个catch块可以串联在一起。此时catch子句的顺序很重要,因为会按顺序检查catch子。catch块11异常处理

多个catch块的计算顺序是从代码的顶部到底部;但对抛出的每个异常,都只执行一个catch块;按顺序检查catch子句,选择与指定的准确类型或其基类最为匹配的第一个catch块;如果没有catch块匹配异常筛选器,则选择无筛选器的catch块(如果语句有的话);将先捕获特定程度较高的异常,而不是特定程度较小的异常。因此需要将带有最具体的(即派生程度最高的)异常类的catch块放在最前面。如果catch块的排序造成后面的块永远不能达到,则编译器将产生错误。catch块11异常处理

可在catch块中使用throw语句重新抛出已由catch语句捕获的异常。以下示例从IOException异常中提取源信息,然后向父方法发送异常。catch(e){//arehandledhere.}catch(IOExceptione){//Extractsomeinformationfromthisexception,andthen//throwittotheparentmethod.if(e.Source!=null)Console.WriteLine("IOExceptionsource:{0}",e.Source);throw;}catch块11异常处理

在将异常传递出去进行额外处理前部分地处理异常。try{//Trytoaccessaresource.}catch(System.UnauthorizedAccessExceptione){//Callacustomerrorloggingprocedure.LogError(e);//Re-throwtheerror.throw;}catch块11异常处理

可以在指定的条件为真时重新引发异常。catch(InvalidCastExceptione){if(e.Data==null)

{throw;}else

{//Takesomeaction.}}如果要再次抛出当前由无参数的catch子句处理的异常,则使用不带参数的throw语句。catch{throw;}catch块11异常处理

创建一个新异常可以新建一个更具体的异常并抛出该异常。intGetInt(int[]array,intindex){try{returnarray[index];}catch(System.IndexOutOfRangeExceptione){thrownewSystem.ArgumentOutOfRangeException("Parameterindexisoutofrange.");}}catch块11异常处理

可捕获一个异常并抛出另一个自定义异常。执行此操作时,指定将其作为内部异常捕获的异常,如catch(InvalidCastExceptione){//Performsomeactionhere,andthenthrowanewexception.thrownewYourCustomException("Putyourerrormessagehere.",e);}catch块11异常处理

try块内只初始化其内部声明的变量。否则,完成对块的执行前,可能会发生异常。staticvoidMain(){intn;try{//Donotinitializethisvariablehere.n=123;}catch{}//Error:Useofunassignedlocalvariable'n'.

Console.Write(n);}try块11异常处理例子classTryFinallyTest{staticvoidProcessString(strings){if(s==null)

{thrownewArgumentNullException();}}staticvoidMain()

{strings=null;//Fordemonstrationpurposes.

try

{ProcessString(s);}

catch(Exceptione)

{Console.WriteLine(“{0}Exceptioncaught.”,e);}}}/*Output:System.ArgumentNullException:Valuecannotbenull.atTryFinallyTest.Main()Exceptioncaught.*/11异常处理

下例使用两个catch语句。捕获先出现的最特定的异常。classThrowTest3{

staticvoidProcessString(strings)

{

if(s==null)

{thrownewArgumentNullException();}}staticvoidMain()

{

try

{strings=null;ProcessString(s);}例子11异常处理catch(ArgumentNullExceptione)

{//Mostspecific:Console.WriteLine("{0}Firstexceptioncaught.",e);}

catch(Exceptione)

{//Leastspecific:Console.WriteLine("{0}Secondexceptioncaught.",e);}}}/*Output:System.ArgumentNullException:Valuecannotbenull.atTest.ThrowTest3.ProcessString(Strings)...Firstexceptioncaught.*/例子11异常处理

在前面的示例中,如果从具体程度最低的catch子句开始,将显示以下错误信息:Apreviouscatchclausealreadycatchesallexceptionsofthisorasupertype('System.Exception')

若要捕获特定程度最小的异常,可以使用下面的语句替换throw语句(但不建议):thrownewException();例子11异常处理如何捕捉非CLS异常包括C++/CLI在内的某些.NET语言允许对象引发不是由Exception派生的异常。这类异常称为“非CLS异常”或“非异常”。在VisualC#中,不能引发非CLS异常,但是可以采用两种方法捕捉这类异常:在catch(Exceptione)块中作为RuntimeWrappedException捕捉。默认情况下,VisualC#程序集将非CLS异常作为包装异常来捕捉。如果需要,可通过WrappedException属性访问原始异常。11异常处理

在位于catch(Exception)或catch(Exceptione)块之后的常规catch块(没有指定异常类型的catch块)中。如果要执行某个操作(如写入日志文件)以响应非CLS异常,并且不需要访问异常信息,可使用此方法。默认情况下,公共语言运行时会包装所有异常。要禁用此行为,需将程序集级别特性添加到代码中,该特性通常在AssemblyInfo.cs文件中。[assembly:RuntimeCompatibilityAttribute(WrapNonExceptionThrows=false)]如何捕捉非CLS异常11异常处理2.4try-finallyfinally块用于清除try块中分配的任何资源,以及运行即使在发生异常时也必须要执行的代码。控制总是传递给finally块,与try块的退出方式无关。finally块将在最后执行,在try块和任何匹配catch的块之后执行。不管是否引发异常或者是否找到与异常类型匹配的catch块,finally始终运行。可以使用finally块释放资源(如文件流、数据库连接和图形句柄),而不用等待由运行时中的垃圾回收器来完成对象。11异常处理

在下面的示例中,使用finally块关闭在try块中打开的文件。注意,在关闭文件之前要检查该文件句柄的状态。如果try块无法打开文件,则文件句柄值为null,此时finally块不会尝试关闭它。如果在try块中成功打开该文件,则finally块将关闭打开的文件。2.4try-finally11异常处理

System.IO.file=null;System.IO.=newSystem.IO.("C:\\");try{file=();(0xF);}finally{//CheckfornullbecauseOpenWritemighthavefailed.if(null){();}}2.4try-finally11异常处理

在下例中,有一个导致异常的无效转换语句。当运行程序时,将收到一条运行时错误信息,但finally子句仍继续执行并显示输出。publicclassThrowTest{staticvoidMain()

{inti=123;strings="Somestring";objecto=s;try

{i=(int)o;}finally{Console.Write(“i={0}”,i);}

}}2.4try-finally11异常处理//*Output:UnhandledException:System.InvalidCastException:Specifiedcastisnotvalid.atValueEquality.ThrowTest.Main()inc:\users\sahnnyj\documents\visualstudio2010\Projects\ConsoleApplication9\Program.cs:line21Thefinallyblockisexecuted,eventhoughanerrorwascaughtinthetryblock.i=123*/2.4try-finally11异常处理using语句C#还提供了using语句(非using指令),该语句提供了与try-finally语句相同功能的简便语法。提供能确保正确使用IDisposable对象的方便语法。指当使用完毕实现了IDisposable接口的对象以后自动调用它的Dispose()方法下例演示如何使用using语句。using(Fontfont1=newFont("Arial",10.0f)){bytecharset=font1.GdiCharSet;}11异常处理

按照规则,当使用IDisposable对象时,应在using语句中声明和实例化此对象。using语句按照正确方式调用对象的Dispose方法释放资源。在using块中对象是只读的并且无法进行修改或重新分配。using语句确保调用Dispose,即使在调用对象上的方法时发生异常也是如此。通过将对象放入try块中,并在finally块中调用Dispose,可以获得相同的结果;实际上,这就是编译器转换using语句的方式。using语句11异常处理

前面的代码示例不使用using语句时可表示为:Fontfont1=newFont("Arial",10.0f);

try{

bytecharset=font1.GdiCharSet;

}finally{if(font1!=null)((IDisposable)font1).Dispose();

}using语句11异常处理可以将多个对象与using语句一起使用,但必须在using语句中声明这些对象,并用逗号隔开,如:using(Fontfont3=newFont("Arial",10.0f),font4=newFont("Arial",10.0f)){//Usefont3andfont4.}using语句11异常处理

也可以先实例化资源对象,然后将变量传递给using语句,但不建议如此做。因为当尝试在using块外部使用该对象,可能导致引发异常。因此,通常最好在using语句中实例化该对象,这将限制其范围在using块中。using语句11异常处理

Fontfont2=newFont("Arial",10.0f);using(font2)//notrecommended{//usefont2}//font2isstillinscope//butthemethodcallthrowsanexceptionfloatf=font2.GetHeight();using语句11异常处理2.5try-catch-finallycatch和finally一起使用的常见方式是:在try块中获取并使用资源,在catch块中处理异常情况,在finally块中释放资源。11异常处理publicclassEHClass{voidReadindex)

{//Torunthiscode,substituteavalidpathfromyourlocalmachinestringpath=@"c:\users\public\test.txt";System.IO.StreamReaderfile=newSystem.IO.StreamReader(path);char[]buffer=newchar[10];try

{(buffer,index,buffer.Length);}

2.5try-catch-finally11异常处理catch(System.IO.IOExceptione){Console.WriteLine("Errorreadingfrom{0}.Message={1}",path,e.Message);}finally

{if(null)

{();}}//Dosomethingwithbuffer...}}2.5try-catch-finally11异常处理3、使用异常在C#中,程序中的运行时错误通过使用一种称为“异常”的机制在程序中传播。异常由遇到错误的代码抛出,由能够更正错误的代码捕捉。异常可由.NETFramework公共语言运行时(CLR)或由程序中的代码抛出。一旦抛出了一个异常,这个异常就会在调用堆栈中往上传播,直到找到针对它的catch语句。未捕获的异常由系统提供的通用异常处理程序处理,该处理程序会显示一个对话框。11异常处理

异常由从Exception派生的类表示。此类标识异常的类型,并包含详细描述异常的属性。抛出异常涉及到创建一个异常派生类的实例,配置异常的属性(可选),然后使用throw关键字抛出该对象。例如:classCustomException:Exception{publicCustomException(stringmessage){}}privatestaticvoidTestThrow(){CustomExceptionex=newCustomException("CustomexceptioninTestThrow()");throwex;}3.1抛出异常11异常处理

当存在下列一种或多种情况时,程序员应抛出异常:方法无法完成其中定义的功能。staticvoidCopyObject(SampleClassoriginal){if(original==null){thrownewSystem.ArgumentException("Parametercannotbenull","original");}}根据对象状态,对某个对象进行不适当的调用。如尝试对只读文件执行写操作。在对象状态不允许某项操作的情况下,抛出InvalidOperationException的一个实例或基于此类的派生类的对象。3.1抛出异常11异常处理

classProgramLog{System.IO.logFile=null;voidOpenLog(System.IO.,

System.IO.mode){}voidWriteLog(){if(!nWrite){thrownewSystem.InvalidOperationException("Logberead-only");}//Elsewritedatatothelogandreturn.}}3.1抛出异常11异常处理

方法的参数导致了异常。应捕获原始异常并创建ArgumentException实例。原始异常作为InnerException参数传递给ArgumentException的构造函数:staticintGetValueFromArray(int[]array,intindex){try{returnarray[index];}catch(System.IndexOutOfRangeExceptionex)

{System.ArgumentExceptionargEx=newSystem.ArgumentException("Indexisoutofrange","index",ex);throwargEx;}}3.1抛出异常11异常处理

抛出异常时要避免的情况不应使用异常来更改正常执行过程中的程序流程。异常只能用于报告和处理错误条件。只能抛出异常,而不能作为返回值或参数返回异常。不要从自己的源代码中有意引发System.Exception、System.SystemException、System.NullReferenceException或System.IndexOutOfRangeException。不要创建可在调试模式下引发但不会在发布模式下引发的异常。3.1抛出异常11异常处理程序可以抛出System命名空间中的预定义的异常类(3.1注明的情况除外),或通过从Exception派生来创建自定义的异常类。自定义派生类至少应定义四个构造函数:默认构造函数;设置消息属性;同时设置Message属性和InnerException属性;第四个构造函数用于序列化异常。新异常类应该可序列化。3.2自定义异常类11异常处理

[Serializable()]publicclassInvalidDepartmentException:System.Exception{publicInvalidDepartmentException():base(){}publicInvalidDepartmentException(stringmessage):base(message){}publicInvalidDepartmentException(stringmessage,System.Exceptioninner):base(message,inner){}//Aconstructorisneededforserializationwhenan//exceptionpropagatesfromaremotingservertotheclient.protectedInvalidDepartmentException(System.Runtime.Serialization.SerializationInfoinfo,System.Runtime.Serialization.StreamingContextcontext){}}3.2自定义异常类11异常处理4、异常类Exception类是所有异常类的基类。大多数异常对象都是Exception的某个派生类的实例;任何从Object类派生的对象都可以作为异常引发。在几乎任何情况下,建议仅抛出和捕捉Exception对象。11异常处理

当发生错误时,系统或当前执行的应用程序通过抛出包含错误信息的异常来报告该错误。抛出异常之后,将由应用程序或默认异常处理程序处理该异常。异常类型支持下面的功能:描述错误的可读文本。当异常发生时,运行时产生文本消息通知用户错误的性质并提供解决该问题的操作建议。4、异常类11异常处理

此文本消息保存在异常对象的Message属性中。在创建异常对象过程中,可以将文本字符串传递给构造函数以描述该特定异常的详细信息。如果没有向构造函数提供错误消息参数,则将使用默认错误消息。发生异常时调用堆栈的状态。StackTrace属性包含可以用来确定代码中错误发生位置的堆栈跟踪。堆栈跟踪列出所有调用的方法和源文件中这些调用所在的行号。4、异常类11异常处理4.1异常层次结构有两种类型的异常:由执行程序生成的异常和由公共语言运行时生成的异常。这些抛出的异常具有一定的层次结构。Exception是异常的基类。若干个异常类直接从Exception继承,其中包括SystemException类

ApplicationException类这两个类构成几乎所有运行时异常的基础。11异常处理

运行时提供的标准异常以及派生类的创建条件异常类型基类型说明示例ExceptionObject所有异常的基类。无(使用此异常的派生类)。SystemException

Exception所有运行时生成的错误的基类。无(使用此异常的派生类)。IndexOutOfRangeException

SystemException仅当错误地对数组进行索引时,才由运行时引发。在数组的有效范围外对数组进行索引:arr[arr.Length+1]NullReferenceException

SystemException仅当引用null对象时,才由运行时引发。objecto=null;o.ToString();AccessViolationException

SystemException

仅在访问无效内存时由运行时引发。当与非托管代码或不安全的托管代码互操作时或者使用无效指针时发生。InvalidOperationException

SystemException当处于无效状态时,由方法引发。从基础集合移除Item后调用Enumerator.GetNext()。11异常处理

ArgumentException

SystemException所有参数异常的基类。无(使用此异常的派生类)。ArgumentNullException

ArgumentException由不允许参数为null的方法引发。Strings=null;"Calculate".IndexOf(s);ArgumentOutOfRangeException

ArgumentException由验证参数是否位于给定范围内的方法引发。Strings="string";s.Chars[9];ExternalException

SystemException在运行时的外部环境中发生或针对这类环境的异常的基类。无(使用此异常的派生类)。ComException

ExternalException封装COMHRESULT信息的异常。在COM互操作中使用。SEHException

ExternalException封装Win32结构化异常处理信息的异常。在非托管代码interop中使用。运行时提供的标准异常以及派生类的创建条件11异常处理编译器生成的异常异常说明ArithmeticException在算术运算期间发生的异常(如DivideByZeroException和OverflowException)的基类。ArrayTypeMismatchException当数组存储给定的元素时,如果由于该元素的实际类型与数组的实际类型不兼容而导致存储失败,就会引发此异常。DivideByZeroException在尝试用零除整数值时引发。IndexOutOfRangeException在尝试为数组设置小于零或超出数组界限的索引时引发。InvalidCastException当从基类型到接口或派生类型的显式转换在运行时失败时,就会引发此异常。下列异常是在基本操作失败时由.NETFramework的公共语言运行时(CLR)自动抛出。11异常处理

NullReferenceException在尝试引用值为null的对象时引发。OutOfMemoryException在使用new运算符分配内存的尝试失败时引发。这表明可用于公共语言运行时的内存已耗尽。OverflowException在checked上下文中的算术运算溢出时引发。StackOverflowException当执行堆栈由于具有太多的挂起方法调用而耗尽时,就会引发此异常;这通常表明存在非常深的递归或无限递归。TypeInitializationException在静态构造函数引发异常并且不存在可以捕捉到它的兼容catch子句时引发。编译器生成的异常11异常处理4.2Exception类表示在应用程序执行期间发生的错误。命名空间:System程序集:mscorlib(在mscorlib.dll中)语法[SerializableAttribute][ComVisibleAttribute(true)][ClassInterfaceAttribute(ClassInterfaceType.None)]publicclassException:ISerializable,_Exception继承层次结构System.Object

System.Exception11异常处理Exception类的属性名称说明Data获取一个提供用户定义的其他异常信息的键/值对的集合。HelpLink获取或设置指向此异常所关联帮助文件的链接。HResult获取或设置

HRESULT,它是分配给特定异常的编码数值。InnerException获取导致当前异常的Exception实例。Message获取描述当前异常的消息。Source获取或设置导致错误的应用程序或对象的名称。StackTrace获取调用堆栈上直接帧的字符串表示形式。TargetSite获取引发当前异常的方法。11异常处理Exception类的属性Exception类的若干属性使了解异常更容易。这些属性包括:StackTrace属性此属性包含可用来确定错误发生位置的堆栈跟踪。如果有可用的调试信息,则堆栈跟踪包含源文件名和程序行号。11异常处理

InnerException属性在异常处理过程中创建和保留一系列异常。创建一个包含以前捕捉异常的新异常;原始异常捕获为第二异常,保存在InnerException属性中,这允许处理第二异常的代码去检查附加信息。例如,假设有一个读取文件并格式化相应数据的方法M。代码尝试从文件读取,但引发。方法M捕捉并引发BadFormatException。在此情况下,可保存在BadFormatException的InnerException属性Exception类的属性11异常处理

Message属性提供有关异常起因的详细信息。Message以异常引发线程的Thread.CurrentUICulture属性所指定的语言显示信息。HelpLink属性可保存某个帮助文件的URL(或URN),该文件提供有关异常起因的大量信息。Data属性可以保存任意数据(以键值对的形式)的IDictionary。Exception类的属性11异常处理

usingSystem;usingSystem.Collections.Generic;usingSystem.Text;namespaceExceptionInfo{classProgram{staticvoidMain(string[]args){try{/*试图将字符串赋值给整型变量时,将会引起异常,从而能输出异常信息*/int.Parse("Error");}Exception类的属性11异常处理catch(Exceptionerr){//获取并输出描述异常的文字信息Console.WriteLine("当前异常的描述为:"+err.Message);//获取并输出引发异常的方法名称Console.WriteLine("引起异常的方法是:"+);//获取并输出异常的来源名称,通常是应用程序的名称Console.WriteLine("异常的来源名称是:"+err.Source);//获取并输出异常产生时,调用堆栈上的程序位置Console.WriteLine("异常在堆栈中的帧:"+err.StackTrace);Console.ReadLine();}}}}Exception类的属性11异常处理4.3SystemException类为System命名空间中的预定义异常定义基类。命名空间:System程序集:mscorlib(在mscorlib.dll中)语法[SerializableAttribute][ComVisibleAttribute(true)]publicclassSystemException:Exception继承层次结构System.Object

System.Exception

System.SystemException11异常处理

SystemException不向Exception添加新功能。此类是作为一种方法提供的,用于区分系统定义的异常和应用程序定义的异常。SystemException不提供导致Exception原因的信息。不建议捕捉和实例化SystemException。大多数情况下都不应引发此类的实例,在应用程序中引发该异常不是好的编程做法。如果需要实例化该类,则应将描述错误的可读消息传递给其构造函数。4.3SystemException类11异常处理4.4ApplicationException类发生非致命应用程序错误时引发的异常。命名空间:System程序集:mscorlib(在mscorlib.dll中)语法[SerializableAttribute][ComVisibleAttribute(true)]publicclassApplicationException:Exception继承层次结构System.ObjectSystem.ExceptionSystem.ApplicationException11异常处理

用户应用程序(不是公共语言运行时)引发从ApplicationException类派生的自定义异常。ApplicationException类区分应用程序定义的异常与系统定义的异常。应从Exception类派生自定义异常,非从ApplicationException类派生。4.4ApplicationException类11异常处理5、异常设计准则异常是报告错误的标准机制。应用程序和库不应使用返回代码来传递错误信息。异常的采用增进了框架设计的一致性,允许无返回类型的成员(如构造函数)报告错误。异常还允许程序处理错误或根据需要终止运行。默认行为是在应用程序不处理引发的异常时,终止应用程序。11异常处理5.1异常抛出当某个成员无法成功执行它应执行的操作时,将会抛出异常。这称为“执行失败”。下列准则可帮助确保在适当时抛出异常:不要返回错误代码。异常是报告框架中错误的主要手段。通过抛出异常来报告执行故障。如果某一成员无法按预期方式成功执行,则应将这种情况视为一个执行故障并抛出一个异常。11异常处理

如果代码遇到继续执行则不安全的情况,应考虑通过调用System.Environment.FailFast(System.String)来终止进程,而不是抛出异常。尽可能不对正常控制流使用异常。除了系统故障及可能导致争用状态的操作之外,框架设计人员还应设计一些API以便用户可以编写不抛出异常的代码。例如,可以提供一种在调用成员之前检查前提条件的方法,以便用户可以编写不抛出异常的代码。5.1异常抛出11异常处理

下面的代码示例演示如何进行测试以防止在消息字符串为null时抛出异常。publicclassDoer{//Methodthatcanpotentialthrowexceptionsoften.publicstaticvoidProcessMessage(stringmessage){if(message==null){thrownewArgumentNullException("message");}}//Othermethods...}5.1异常抛出11异常处理publicclassTester{publicstaticvoidTesterDoer(ICollection<string>messages){foreach(stringmessageinmessages){//Testtoensurethatthecallwon'tcausetheexception.if(message!=null){Doer.ProcessMessage(message);}}}}5.1异常抛出11异常处理

考虑抛出异常的性能影响。记录公共可调用的成员因成员协定冲突(而不是系统故障)而抛出的所有异常,并将这些异常视为协定的一部分。包含在协定中的异常不应从一个版本更改到下一个版本。不要包含可以根据某一选项抛出或不抛出异常的公共成员。不要包含将异常作为返回值或输出参数返回的公共成员。5.1异常抛出11异常处理

考虑使用异常生成器方法。从不同的位置抛出同一异常会经常发生。为了避免代码膨胀,请使用帮助器方法创建异常并初始化其属性。避免从finally块中显式抛出异常。可以接受因调用抛出异常的方法而隐式抛出的异常。5.1异常抛出11异常处理选择要抛出的正确异常类型下列设计准则可确保正确地使用现有异常,并在适当的时候创建对库有价值的新异常。考虑引发System命名空间中的现有异常,而不是创建自定义异常类型。如果错误状态可以通过不同于现有任何其他异常的方法以编程方式进行处理,则要创建并抛出自定义异常。否则,抛出一个现有异常。不要只是为了获得异常而创建和抛出新异常。11异常处理

抛出适当的最具体(派生程度最大)的异常。例如,如果某方法收到一个null(在VisualBasic中为Nothing)参数,则该方法应引发System.ArgumentNullException,而不是引发该异常的基类型System.ArgumentException。选择要抛出的正确异常类型11异常处理5.2异常处理下面的准则有助于确保库正确处理异常。不要通过在框架代码或程序中捕捉非特定异常(如System.Exception、System.SystemException等)来处理错误。如果捕捉异常是为了再次引发或传输给其他线程,则可以捕捉这些异常。下面的代码示例演示的异常处理是不正确的。11异常处理

publicclassBadExceptionHandlingExample1{publicvoidDoWork(){//Dosomeworkthatmightthrowexceptions.}publicvoidMethodWithBadHandler(){try{DoWork();}catch(Exceptione){//Handletheexceptionandcontinueexecuting.}}}5.2异常处理11异常处理

如果捕捉异常是为了传输异常,则不要排除任何特殊异常。只捕捉能够合法处理的异常,而不要在catch子句中创建特殊异常的列表。在非特定异常处理程序中,不能处理的异常不应视为特殊处理的特殊情况。下面的代码示例演示对以再次引发为目的特殊异常进行的不正确测试。5.2异常处理11异常处理

publicclassBadExceptionHandlingExample2{publicvoidDoWork(){//Dosomeworkthatmightthrowexceptions.}publicvoidMethodWithBadHandler(){try{DoWork();}catch(Exceptione){if(eisStackOverflowException||eisOutOfMemoryException)throw;//Handletheexceptionandcontinueexecuting.}}}5.2异常处理11异常处理

如果了解特定异常在给定上下文中引发的条件,请考虑捕捉这些异常。应该只捕捉可以从中恢复的异常。例如,尝试打开不存在的文件而导致的

可以由应用程序处理,因为应用程序可以将问题传达给用户,并允许用户指定其他文件名或创建该文件。如打开文件的请求会生成ExecutionEngineException,则不应该处理该请求,因为没有任何把握可以了解该异常的基础原因,应用程序也无法确保继续执行是安全的。不要过多使用catch。通常应允许异常在调用堆栈中往上传播。捕捉无法合法处理的异常会隐藏关键的调试信息。5.2异常处理11异常处理

使用try-finally并避免将try-catch用于清理代码。书写规范的异常代码中,try-finally比try-catch更为常用使用catch子句是为了允许处理异常(例如,通过纪录非致命错误)无论是否抛出了异常,使用finally子句即可执行清理代码如果分配了昂贵或有限的资源(如数据库连接或流),则应将释放这些资源的代码放置在finally块中。捕捉并再次抛出异常时,优先使用空抛出。这是保留异常调用堆栈的最佳方式。不要使用无参数catch块来处理不符合CLS的异常(不是从System.Exception派生的异常)。5.2异常处理11异常处理5.3捕捉和抛出标准异常类型下面的准则介绍.NETFramework所提供的某些最常用异常的最佳做法。Exception和SystemException不要抛出System.Exception或System.SystemException不要在框架代码中捕捉System.Exception或System.SystemException,除非打算再次抛出。避免捕捉System.Exception或System.SystemException,在顶级异常处理程序中除外。11异常处理

ApplicationException一定要从T:System.Exception类而不是T:System.ApplicationException类派生自定义异常。最初考虑自定义异常应该从ApplicationException类派生

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论