異常處理課件_第1頁
異常處理課件_第2頁
異常處理課件_第3頁
異常處理課件_第4頁
異常處理課件_第5頁
已閱讀5頁,還剩112頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

11異常處理異常處理11異常處理1、.NETFramework中的異常異常是正在執(zhí)行的程序所遇到的任何錯誤情況或意外行為。下面這些情況都可引發(fā)異常:應(yīng)用程序代碼或其調(diào)用的代碼(如共享庫)中有錯誤;操作系統(tǒng)資源不可用;公共語言運(yùn)行時遇到意外情況(如無法驗證代碼)等等。11異常處理在.NETFramework中,異常是從System.Exception類繼承的對象。異常從發(fā)生問題的代碼區(qū)域引發(fā),然后沿堆棧向上傳遞,直到應(yīng)用程序處理它或程序終止。1、.NETFramework中的異常11異常處理1.1異常處理與傳統(tǒng)的錯誤處理方法傳統(tǒng)上,語言的錯誤處理模型有兩種:語言采用自己獨(dú)特的方式來檢測錯誤并定位錯誤處理程序;依賴于操作系統(tǒng)提供的錯誤處理機(jī)制。運(yùn)行時異常處理具有以下特點(diǎn):處理異常時不用考慮該異常的生成或處理語言;異常處理時不要求任何特定的語言語法,而是允許每種語言定義自己的語法;允許跨進(jìn)程甚至跨計算機(jī)邊界引發(fā)異常。11異常處理

與其他錯誤通知方法相比,異常具有以下優(yōu)點(diǎn):不再有出現(xiàn)錯誤而不被人注意的情況;無效值不會繼續(xù)在系統(tǒng)中傳播;不必檢查返回代碼;可以輕松添加異常處理代碼,以增加程序的可靠性;運(yùn)行時的異常處理比基于Windows的C++錯誤處理更快。由于執(zhí)行線程例行地遍歷托管代碼塊和非托管代碼塊,因此運(yùn)行時可以拋出或捕獲托管或非托管代碼中的異常。非托管代碼可以同時包含C++樣式的SEH異常和基于COM的HRESULT。1.1異常處理與傳統(tǒng)的錯誤處理方法11異常處理1.2運(yùn)行時如何管理異常運(yùn)行時的異常處理模型是基于異常對象和受保護(hù)代碼塊。出現(xiàn)異常時,創(chuàng)建一個Exception對象來表示該異常。運(yùn)行時為每個可執(zhí)行文件創(chuàng)建一個異常信息表。在異常信息表中,可執(zhí)行文件的每個方法都有一個關(guān)聯(lián)的異常處理信息數(shù)組(可以為空)。數(shù)組中的每一項描述一個受保護(hù)的代碼塊、任何與該代碼關(guān)聯(lián)的異常篩選器和任何異常處理程序(catch語句)。此異常表非常有效,僅在異常發(fā)生時使用資源;在沒有異常發(fā)生時,它不會引起處理器時間或內(nèi)存使用方面的任何性能損失。11異常處理

異常信息表為受保護(hù)代碼塊提供了四種類型的異常處理程序:finally處理程序,每當(dāng)“塊”退出時它都會執(zhí)行,不考慮退出是由正??刂屏饕鸬倪€是由未經(jīng)處理的異常引起。錯誤處理程序,在異常發(fā)生時一定執(zhí)行,但在正??刂屏魍瓿蓵r不執(zhí)行。類型篩選的處理程序,它處理指定類或其派生類的任何異常。用戶篩選的處理程序,它運(yùn)行用戶指定的代碼,來確定異常應(yīng)由關(guān)聯(lián)的處理程序處理還是應(yīng)傳遞給下一個受保護(hù)的塊。每種語言根據(jù)自己的規(guī)范實現(xiàn)這些異常處理程序。1.2運(yùn)行時如何管理異常11異常處理

異常發(fā)生時,運(yùn)行時分兩步來處理:運(yùn)行時在數(shù)組中搜索執(zhí)行下列操作的第一個受保護(hù)塊:保護(hù)包含當(dāng)前執(zhí)行的指令的區(qū)域。包含異常處理程序或包含處理異常的篩選器。如果出現(xiàn)匹配項,則運(yùn)行時會創(chuàng)建一個Exception對象來描述該異常。然后運(yùn)行時執(zhí)行位于該異常的發(fā)生語句和處理語句之間的所有finally語句或錯誤語句。異常處理程序的順序很重要;最里面的異常處理程序最先計算。異常處理程序可以訪問捕捉異常程序中的局部變量和本地內(nèi)存,但異常發(fā)生時的任何中間值都會丟失。1.2運(yùn)行時如何管理異常11異常處理1.3篩選運(yùn)行時異??梢园搭愋突虬茨承┯脩舳x的條件對捕捉和處理的異常進(jìn)行篩選。類型篩選的處理程序管理特定類型異?;蛘呤瞧渑缮悺H鏲atch(e){Console.WriteLine("[Data]{0}",e);}用戶篩選的異常處理程序根據(jù)用戶為異常定義的要求來捕捉和處理異常。11異常處理

如果當(dāng)前方法中沒有出現(xiàn)匹配項,則運(yùn)行時搜索當(dāng)前方法的每一個調(diào)用方,并沿著堆棧一直向上查找。如果任何調(diào)用方都沒有匹配項,則運(yùn)行時允許調(diào)試器訪問該異常。如果調(diào)試器不能附加到該異常,則運(yùn)行時引發(fā)AppDomain.UnhandledException事件。如果沒有該事件的偵聽器,則運(yùn)行時轉(zhuǎn)儲堆棧跟蹤并結(jié)束應(yīng)用程序。1.3篩選運(yùn)行時異常11異常處理1.4處理異常的最佳做法設(shè)計良好的錯誤處理代碼塊集使程序更可靠并且不容易崩潰。下面列出關(guān)于異常處理最佳做法方面的建議:知道何時設(shè)置Try/Catch塊。所選擇的方法依賴于預(yù)計事件發(fā)生的頻率。如果事件確實是異常的并且是一個錯誤(如意外的文件尾),則使用異常處理比較好,因為正常情況下執(zhí)行的代碼更少。如果事件是例行發(fā)生的,使用編程方法檢查錯誤比較好。在此情況下,如果發(fā)生異常,將需要更長的時間處理。11異常處理

在可能生成異常的代碼周圍使用Try/Finally塊,并將Catch語句集中在一個位置。以這種方式,Try語句生成異常,F(xiàn)inally語句關(guān)閉或釋放資源,而Catch語句從中心位置處理異常。始終按從最特殊到最不特殊的順序?qū)atch塊中的異常排序。此方法將保證特殊異常在傳遞給更常規(guī)的Catch塊之前被處理。以“Exception”這個詞作為異常類名的結(jié)尾。例如:

publicclassMy:Exception{

}

1.4處理異常的最佳做法11異常處理

當(dāng)創(chuàng)建用戶定義的異常時,必須確保異常的元數(shù)據(jù)對遠(yuǎn)程執(zhí)行的代碼可用,包括當(dāng)異常跨應(yīng)用程序域發(fā)生時。例如,假設(shè)應(yīng)用程序域A創(chuàng)建應(yīng)用程序域B,后者執(zhí)行引發(fā)異常代碼。A若想正確捕獲和處理異常,它必須能夠找到包含B所引發(fā)的異常的程序集。如果包含B引發(fā)的異常的程序集位于B的應(yīng)用程序基目錄下,而不是位于A的應(yīng)用程序基目錄下,則A將無法找到異常,此時將引發(fā)異常。為避免此情況,可以兩種方式部署包含異常信息的程序集:將程序集放在兩個應(yīng)用程序域共享的公共應(yīng)用程序基中如果兩個應(yīng)用程序域不共享一個公共應(yīng)用程序基,則用強(qiáng)名稱給包含異常信息的程序集簽名并將其部署到全局程序集緩存中。1.4處理異常的最佳做法11異常處理

在大多數(shù)情況下,使用預(yù)定義的異常類型。但是在程序中可以定義新異常類型。引入新異常類,使程序員能夠根據(jù)異常的不同在代碼中采取不同的操作。在C#和C++中創(chuàng)建自己的異常類時,至少使用三個公共構(gòu)造函數(shù)。對于大多數(shù)應(yīng)用程序,從Exception類派生自定義異常。在每個異常中都包含一個本地化描述字符串。當(dāng)用戶看到錯誤消息時,該消息從拋出異常的描述字符串派生,而不是從異常類派生。1.4處理異常的最佳做法11異常處理

使用語法上正確的錯誤消息。在異常的描述字符串中,每個句子都應(yīng)以句號結(jié)尾。為編程訪問提供Exception屬性。僅當(dāng)程序需要附加信息時,才在異常中包含附加信息(不包括描述字符串)。對極常見的錯誤情況返回null。例如,如果沒找到文件,Open將返回null;但如果文件被鎖定,則引發(fā)異常。類的設(shè)計應(yīng)保證其在正常使用中不引發(fā)異常。例如,類提供一種確定是否已到達(dá)文件末尾的方法。這避免了在讀取超過文件尾時引發(fā)的異常。見下例: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#語言的異常處理功能:幫助程序員處理程序運(yùn)行時出現(xiàn)的任何意外或異常情況。異常處理使用try、catch和finally關(guān)鍵字嘗試某些可能失敗的操作,以處理失敗情況。公共語言運(yùn)行時(CLR)、.NETFramework或任何第三方庫或者應(yīng)用程序代碼都可以生成異常。異??梢允褂胻hrow關(guān)鍵字創(chuàng)建。11異常處理

很多情況下,異??赡懿皇怯纱a直接調(diào)用的方法引發(fā),而是由所調(diào)用堆棧中位置更靠下的另一個方法所引發(fā)。在這種情況下,CLR將展開堆棧,查找是否有方法包含了針對該特定異常類型的catch塊,如果找到這樣的方法,就會執(zhí)行找到的第一個這樣的catch塊。如果在調(diào)用堆棧中的任何位置都沒有找到適當(dāng)?shù)腸atch塊,就會終止該進(jìn)程,并向用戶顯示一條消息。2、異常處理11異常處理

示例:使用一個方法檢測是否有被零除的情況;如果有異常處理,則捕獲該錯誤。如果沒有異常處理,此程序?qū)⒔K止并產(chǎn)生“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派生而來。在可能引發(fā)異常的語句周圍使用try塊。一旦try塊中發(fā)生異常,控制流將跳轉(zhuǎn)到第一個關(guān)聯(lián)的異常處理程序(無論該處理程序存在于調(diào)用堆棧中的什么位置)。在C#中,catch關(guān)鍵字用于定義異常處理程序。11異常處理

如果給定異常沒有異常處理程序,則程序?qū)⑼V箞?zhí)行,并顯示一條錯誤消息。除非可以處理某個異常并使應(yīng)用程序處于已知狀態(tài),否則請不要捕捉該異常。如果catch塊定義了一個異常變量,則可以用它獲取有關(guān)所發(fā)生異常類型的更多信息。無論是否產(chǎn)生異常,finally塊中的代碼都會被執(zhí)行。使用finally塊釋放資源,例如關(guān)閉在try塊中打開的任何流或文件。異常概述11異常處理2.1異常處理語句C#為處理在程序執(zhí)行期間可能出現(xiàn)的反常情況(稱作異常)提供內(nèi)置支持。這些異常由正??刂屏髦獾拇a處理。throwtry-catchtry-finallytry-catch-finally不帶有catch或finally塊的try塊將導(dǎo)致編譯器錯誤。11異常處理2.2throwthrow語句用于拋出程序執(zhí)行期間出現(xiàn)的異常情況。拋出的異常是一個對象,如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異常處理如何顯式引發(fā)異常可以使用throw語句顯式拋出異常??梢允褂胻hrow語句再次拋出捕獲的異常。較好的編碼做法是,向再次拋出的異常添加信息以在調(diào)試時提供更多信息。下面的代碼示例使用try/catch塊捕獲可能的。try塊后面是catch塊,catch塊捕獲,如果找不到數(shù)據(jù)文件,則向控制臺寫入消息。下一條語句是throw語句,該語句引發(fā)新的并向該異常添加文本信息。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);}如何:顯式引發(fā)異常11異常處理catch(e){Console.WriteLine("[Data]{0}",e);thrownew(@"[data.txtnotinc:\tempdirectory]",e);}finally{if(fs!=null)fs.Close();}}}如何顯式引發(fā)異常11異常處理2.3try-catchtry-catch語句由一個try塊后跟一個或多個catch子句構(gòu)成,這些子句指定不同的異常處理程序。引發(fā)異常時,公共語言運(yùn)行時(CLR)會查找處理此異常的catch語句。如果當(dāng)前執(zhí)行的方法不包含這樣的catch塊,則CLR會查看調(diào)用當(dāng)前方法的方法,然后會遍歷調(diào)用堆棧。如果找不到catch塊,則CLR會向用戶顯示一條有關(guān)未經(jīng)處理的異常的消息并停止執(zhí)行程序。11異常處理catch塊catch塊可以指定要捕捉的異常類型。類型規(guī)范稱為“異常篩選器”。異常類型應(yīng)從Exception派生出來。一般而言,不會將Exception指定為異常篩選器,除非知道如何處理try塊中可能引發(fā)的所有異常,或者在catch塊中包括了throw語句。雖然可以使用不帶參數(shù)的catch子句捕捉任何類型的異常,但不推薦這種用法。通常,應(yīng)該只捕捉那些知道如何從中恢復(fù)的異常。因此,應(yīng)該總是指定一個從System.Exception派生的對象參數(shù)。11異常處理

例如:catch(InvalidCastExceptione){}在同一個try-catch語句中可以使用一個以上的特定catch子句;即具有不同異常篩選器的多個catch塊可以串聯(lián)在一起。此時catch子句的順序很重要,因為會按順序檢查catch子。catch塊11異常處理

多個catch塊的計算順序是從代碼的頂部到底部;但對拋出的每個異常,都只執(zhí)行一個catch塊;按順序檢查catch子句,選擇與指定的準(zhǔn)確類型或其基類最為匹配的第一個catch塊;如果沒有catch塊匹配異常篩選器,則選擇無篩選器的catch塊(如果語句有的話);將先捕獲特定程度較高的異常,而不是特定程度較小的異常。因此需要將帶有最具體的(即派生程度最高的)異常類的catch塊放在最前面。如果catch塊的排序造成后面的塊永遠(yuǎn)不能達(dá)到,則編譯器將產(chǎn)生錯誤。catch塊11異常處理

可在catch塊中使用throw語句重新拋出已由catch語句捕獲的異常。以下示例從IOException異常中提取源信息,然后向父方法發(fā)送異常。catch(e){//arehandledhere.}catch(IOExceptione){//Extractsomeinformationfromthisexception,andthen//throwittotheparentmethod.if(e.Source!=null)Console.WriteLine("IOExceptionsource:{0}",e.Source);throw;}catch塊11異常處理

在將異常傳遞出去進(jìn)行額外處理前部分地處理異常。try{//Trytoaccessaresource.}catch(System.UnauthorizedAccessExceptione){//Callacustomerrorloggingprocedure.LogError(e);//Re-throwtheerror.throw;}catch塊11異常處理

可以在指定的條件為真時重新引發(fā)異常。catch(InvalidCastExceptione){if(e.Data==null)

{throw;}else

{//Takesomeaction.}}如果要再次拋出當(dāng)前由無參數(shù)的catch子句處理的異常,則使用不帶參數(shù)的throw語句。catch{throw;}catch塊11異常處理

創(chuàng)建一個新異常可以新建一個更具體的異常并拋出該異常。intGetInt(int[]array,intindex){try{returnarray[index];}catch(System.IndexOutOfRangeExceptione){thrownewSystem.ArgumentOutOfRangeException("Parameterindexisoutofrange.");}}catch塊11異常處理

可捕獲一個異常并拋出另一個自定義異常。執(zhí)行此操作時,指定將其作為內(nèi)部異常捕獲的異常,如catch(InvalidCastExceptione){//Performsomeactionhere,andthenthrowanewexception.thrownewYourCustomException("Putyourerrormessagehere.",e);}catch塊11異常處理

try塊內(nèi)只初始化其內(nèi)部聲明的變量。否則,完成對塊的執(zhí)行前,可能會發(fā)生異常。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語句。捕獲先出現(xiàn)的最特定的異常。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在內(nèi)的某些.NET語言允許對象引發(fā)不是由Exception派生的異常。這類異常稱為“非CLS異?!被颉胺钱惓!?。在VisualC#中,不能引發(fā)非CLS異常,但是可以采用兩種方法捕捉這類異常:在catch(Exceptione)塊中作為RuntimeWrappedException捕捉。默認(rèn)情況下,VisualC#程序集將非CLS異常作為包裝異常來捕捉。如果需要,可通過WrappedException屬性訪問原始異常。11異常處理

在位于catch(Exception)或catch(Exceptione)塊之后的常規(guī)catch塊(沒有指定異常類型的catch塊)中。如果要執(zhí)行某個操作(如寫入日志文件)以響應(yīng)非CLS異常,并且不需要訪問異常信息,可使用此方法。默認(rèn)情況下,公共語言運(yùn)行時會包裝所有異常。要禁用此行為,需將程序集級別特性添加到代碼中,該特性通常在AssemblyInfo.cs文件中。[assembly:RuntimeCompatibilityAttribute(WrapNonExceptionThrows=false)]如何捕捉非CLS異常11異常處理2.4try-finallyfinally塊用于清除try塊中分配的任何資源,以及運(yùn)行即使在發(fā)生異常時也必須要執(zhí)行的代碼??刂瓶偸莻鬟f給finally塊,與try塊的退出方式無關(guān)。finally塊將在最后執(zhí)行,在try塊和任何匹配catch的塊之后執(zhí)行。不管是否引發(fā)異?;蛘呤欠裾业脚c異常類型匹配的catch塊,finally始終運(yùn)行??梢允褂胒inally塊釋放資源(如文件流、數(shù)據(jù)庫連接和圖形句柄),而不用等待由運(yùn)行時中的垃圾回收器來完成對象。11異常處理

在下面的示例中,使用finally塊關(guān)閉在try塊中打開的文件。注意,在關(guān)閉文件之前要檢查該文件句柄的狀態(tài)。如果try塊無法打開文件,則文件句柄值為null,此時finally塊不會嘗試關(guān)閉它。如果在try塊中成功打開該文件,則finally塊將關(guān)閉打開的文件。2.4try-finally11異常處理

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

在下例中,有一個導(dǎo)致異常的無效轉(zhuǎn)換語句。當(dāng)運(yùn)行程序時,將收到一條運(yùn)行時錯誤信息,但finally子句仍繼續(xù)執(zhí)行并顯示輸出。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對象的方便語法。指當(dāng)使用完畢實現(xiàn)了IDisposable接口的對象以后自動調(diào)用它的Dispose()方法下例演示如何使用using語句。using(Fontfont1=newFont("Arial",10.0f)){bytecharset=font1.GdiCharSet;}11異常處理

按照規(guī)則,當(dāng)使用IDisposable對象時,應(yīng)在using語句中聲明和實例化此對象。using語句按照正確方式調(diào)用對象的Dispose方法釋放資源。在using塊中對象是只讀的并且無法進(jìn)行修改或重新分配。using語句確保調(diào)用Dispose,即使在調(diào)用對象上的方法時發(fā)生異常也是如此。通過將對象放入try塊中,并在finally塊中調(diào)用Dispose,可以獲得相同的結(jié)果;實際上,這就是編譯器轉(zhuǎn)換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語句,但不建議如此做。因為當(dāng)嘗試在using塊外部使用該對象,可能導(dǎo)致引發(fā)異常。因此,通常最好在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#中,程序中的運(yùn)行時錯誤通過使用一種稱為“異常”的機(jī)制在程序中傳播。異常由遇到錯誤的代碼拋出,由能夠更正錯誤的代碼捕捉。異常可由.NETFramework公共語言運(yùn)行時(CLR)或由程序中的代碼拋出。一旦拋出了一個異常,這個異常就會在調(diào)用堆棧中往上傳播,直到找到針對它的catch語句。未捕獲的異常由系統(tǒng)提供的通用異常處理程序處理,該處理程序會顯示一個對話框。11異常處理

異常由從Exception派生的類表示。此類標(biāo)識異常的類型,并包含詳細(xì)描述異常的屬性。拋出異常涉及到創(chuàng)建一個異常派生類的實例,配置異常的屬性(可選),然后使用throw關(guān)鍵字拋出該對象。例如:classCustomException:Exception{publicCustomException(stringmessage){}}privatestaticvoidTestThrow(){CustomExceptionex=newCustomException("CustomexceptioninTestThrow()");throwex;}3.1拋出異常11異常處理

當(dāng)存在下列一種或多種情況時,程序員應(yīng)拋出異常:方法無法完成其中定義的功能。staticvoidCopyObject(SampleClassoriginal){if(original==null){thrownewSystem.ArgumentException("Parametercannotbenull","original");}}根據(jù)對象狀態(tài),對某個對象進(jìn)行不適當(dāng)?shù)恼{(diào)用。如嘗試對只讀文件執(zhí)行寫操作。在對象狀態(tài)不允許某項操作的情況下,拋出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異常處理

方法的參數(shù)導(dǎo)致了異常。應(yīng)捕獲原始異常并創(chuàng)建ArgumentException實例。原始異常作為InnerException參數(shù)傳遞給ArgumentException的構(gòu)造函數(shù):staticintGetValueFromArray(int[]array,intindex){try{returnarray[index];}catch(System.IndexOutOfRangeExceptionex)

{System.ArgumentExceptionargEx=newSystem.ArgumentException("Indexisoutofrange","index",ex);throwargEx;}}3.1拋出異常11異常處理

拋出異常時要避免的情況不應(yīng)使用異常來更改正常執(zhí)行過程中的程序流程。異常只能用于報告和處理錯誤條件。只能拋出異常,而不能作為返回值或參數(shù)返回異常。不要從自己的源代碼中有意引發(fā)System.Exception、System.SystemException、System.NullReferenceException或System.IndexOutOfRangeException。不要創(chuàng)建可在調(diào)試模式下引發(fā)但不會在發(fā)布模式下引發(fā)的異常。3.1拋出異常11異常處理程序可以拋出System命名空間中的預(yù)定義的異常類(3.1注明的情況除外),或通過從Exception派生來創(chuàng)建自定義的異常類。自定義派生類至少應(yīng)定義四個構(gòu)造函數(shù):默認(rèn)構(gòu)造函數(shù);設(shè)置消息屬性;同時設(shè)置Message屬性和InnerException屬性;第四個構(gòu)造函數(shù)用于序列化異常。新異常類應(yīng)該可序列化。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類是所有異常類的基類。大多數(shù)異常對象都是Exception的某個派生類的實例;任何從Object類派生的對象都可以作為異常引發(fā)。在幾乎任何情況下,建議僅拋出和捕捉Exception對象。11異常處理

當(dāng)發(fā)生錯誤時,系統(tǒng)或當(dāng)前執(zhí)行的應(yīng)用程序通過拋出包含錯誤信息的異常來報告該錯誤。拋出異常之后,將由應(yīng)用程序或默認(rèn)異常處理程序處理該異常。異常類型支持下面的功能:描述錯誤的可讀文本。當(dāng)異常發(fā)生時,運(yùn)行時產(chǎn)生文本消息通知用戶錯誤的性質(zhì)并提供解決該問題的操作建議。4、異常類11異常處理

此文本消息保存在異常對象的Message屬性中。在創(chuàng)建異常對象過程中,可以將文本字符串傳遞給構(gòu)造函數(shù)以描述該特定異常的詳細(xì)信息。如果沒有向構(gòu)造函數(shù)提供錯誤消息參數(shù),則將使用默認(rèn)錯誤消息。發(fā)生異常時調(diào)用堆棧的狀態(tài)。StackTrace屬性包含可以用來確定代碼中錯誤發(fā)生位置的堆棧跟蹤。堆棧跟蹤列出所有調(diào)用的方法和源文件中這些調(diào)用所在的行號。4、異常類11異常處理4.1異常層次結(jié)構(gòu)有兩種類型的異常:由執(zhí)行程序生成的異常和由公共語言運(yùn)行時生成的異常。這些拋出的異常具有一定的層次結(jié)構(gòu)。Exception是異常的基類。若干個異常類直接從Exception繼承,其中包括SystemException類

ApplicationException類這兩個類構(gòu)成幾乎所有運(yùn)行時異常的基礎(chǔ)。11異常處理

運(yùn)行時提供的標(biāo)準(zhǔn)異常以及派生類的創(chuàng)建條件異常類型基類型說明示例ExceptionObject所有異常的基類。無(使用此異常的派生類)。SystemException

Exception所有運(yùn)行時生成的錯誤的基類。無(使用此異常的派生類)。IndexOutOfRangeException

SystemException僅當(dāng)錯誤地對數(shù)組進(jìn)行索引時,才由運(yùn)行時引發(fā)。在數(shù)組的有效范圍外對數(shù)組進(jìn)行索引:arr[arr.Length+1]NullReferenceException

SystemException僅當(dāng)引用null對象時,才由運(yùn)行時引發(fā)。objecto=null;o.ToString();AccessViolationException

SystemException

僅在訪問無效內(nèi)存時由運(yùn)行時引發(fā)。當(dāng)與非托管代碼或不安全的托管代碼互操作時或者使用無效指針時發(fā)生。InvalidOperationException

SystemException當(dāng)處于無效狀態(tài)時,由方法引發(fā)。從基礎(chǔ)集合移除Item后調(diào)用Enumerator.GetNext()。11異常處理

ArgumentException

SystemException所有參數(shù)異常的基類。無(使用此異常的派生類)。ArgumentNullException

ArgumentException由不允許參數(shù)為null的方法引發(fā)。Strings=null;"Calculate".IndexOf(s);ArgumentOutOfRangeException

ArgumentException由驗證參數(shù)是否位于給定范圍內(nèi)的方法引發(fā)。Strings="string";s.Chars[9];ExternalException

SystemException在運(yùn)行時的外部環(huán)境中發(fā)生或針對這類環(huán)境的異常的基類。無(使用此異常的派生類)。ComException

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

ExternalException封裝Win32結(jié)構(gòu)化異常處理信息的異常。在非托管代碼interop中使用。運(yùn)行時提供的標(biāo)準(zhǔn)異常以及派生類的創(chuàng)建條件11異常處理編譯器生成的異常異常說明ArithmeticException在算術(shù)運(yùn)算期間發(fā)生的異常(如DivideByZeroException和OverflowException)的基類。ArrayTypeMismatchException當(dāng)數(shù)組存儲給定的元素時,如果由于該元素的實際類型與數(shù)組的實際類型不兼容而導(dǎo)致存儲失敗,就會引發(fā)此異常。DivideByZeroException在嘗試用零除整數(shù)值時引發(fā)。IndexOutOfRangeException在嘗試為數(shù)組設(shè)置小于零或超出數(shù)組界限的索引時引發(fā)。InvalidCastException當(dāng)從基類型到接口或派生類型的顯式轉(zhuǎn)換在運(yùn)行時失敗時,就會引發(fā)此異常。下列異常是在基本操作失敗時由.NETFramework的公共語言運(yùn)行時(CLR)自動拋出。11異常處理

NullReferenceException在嘗試引用值為null的對象時引發(fā)。OutOfMemoryException在使用new運(yùn)算符分配內(nèi)存的嘗試失敗時引發(fā)。這表明可用于公共語言運(yùn)行時的內(nèi)存已耗盡。OverflowException在checked上下文中的算術(shù)運(yùn)算溢出時引發(fā)。StackOverflowException當(dāng)執(zhí)行堆棧由于具有太多的掛起方法調(diào)用而耗盡時,就會引發(fā)此異常;這通常表明存在非常深的遞歸或無限遞歸。TypeInitializationException在靜態(tài)構(gòu)造函數(shù)引發(fā)異常并且不存在可以捕捉到它的兼容catch子句時引發(fā)。編譯器生成的異常11異常處理4.2Exception類表示在應(yīng)用程序執(zhí)行期間發(fā)生的錯誤。命名空間:System程序集:mscorlib(在mscorlib.dll中)語法[SerializableAttribute][ComVisibleAttribute(true)][ClassInterfaceAttribute(ClassInterfaceType.None)]publicclassException:ISerializable,_Exception繼承層次結(jié)構(gòu)System.Object

System.Exception11異常處理Exception類的屬性名稱說明Data獲取一個提供用戶定義的其他異常信息的鍵/值對的集合。HelpLink獲取或設(shè)置指向此異常所關(guān)聯(lián)幫助文件的鏈接。HResult獲取或設(shè)置

HRESULT,它是分配給特定異常的編碼數(shù)值。InnerException獲取導(dǎo)致當(dāng)前異常的Exception實例。Message獲取描述當(dāng)前異常的消息。Source獲取或設(shè)置導(dǎo)致錯誤的應(yīng)用程序或?qū)ο蟮拿Q。StackTrace獲取調(diào)用堆棧上直接幀的字符串表示形式。TargetSite獲取引發(fā)當(dāng)前異常的方法。11異常處理Exception類的屬性Exception類的若干屬性使了解異常更容易。這些屬性包括:StackTrace屬性此屬性包含可用來確定錯誤發(fā)生位置的堆棧跟蹤。如果有可用的調(diào)試信息,則堆棧跟蹤包含源文件名和程序行號。11異常處理

InnerException屬性在異常處理過程中創(chuàng)建和保留一系列異常。創(chuàng)建一個包含以前捕捉異常的新異常;原始異常捕獲為第二異常,保存在InnerException屬性中,這允許處理第二異常的代碼去檢查附加信息。例如,假設(shè)有一個讀取文件并格式化相應(yīng)數(shù)據(jù)的方法M。代碼嘗試從文件讀取,但引發(fā)。方法M捕捉并引發(fā)BadFormatException。在此情況下,可保存在BadFormatException的InnerException屬性Exception類的屬性11異常處理

Message屬性提供有關(guān)異常起因的詳細(xì)信息。Message以異常引發(fā)線程的Thread.CurrentUICulture屬性所指定的語言顯示信息。HelpLink屬性可保存某個幫助文件的URL(或URN),該文件提供有關(guān)異常起因的大量信息。Data屬性可以保存任意數(shù)據(jù)(以鍵值對的形式)的IDictionary。Exception類的屬性11異常處理

usingSystem;usingSystem.Collections.Generic;usingSystem.Text;namespaceExceptionInfo{classProgram{staticvoidMain(string[]args){try{/*試圖將字符串賦值給整型變量時,將會引起異常,從而能輸出異常信息*/int.Parse("Error");}Exception類的屬性11異常處理catch(Exceptionerr){//獲取并輸出描述異常的文字信息Console.WriteLine("當(dāng)前異常的描述為:"+err.Message);//獲取并輸出引發(fā)異常的方法名稱Console.WriteLine("引起異常的方法是:"+);//獲取并輸出異常的來源名稱,通常是應(yīng)用程序的名稱Console.WriteLine("異常的來源名稱是:"+err.Source);//獲取并輸出異常產(chǎn)生時,調(diào)用堆棧上的程序位置Console.WriteLine("異常在堆棧中的幀:"+err.StackTrace);Console.ReadLine();}}}}Exception類的屬性11異常處理4.3SystemException類為System命名空間中的預(yù)定義異常定義基類。命名空間:System程序集:mscorlib(在mscorlib.dll中)語法[SerializableAttribute][ComVisibleAttribute(true)]publicclassSystemException:Exception繼承層次結(jié)構(gòu)System.Object

System.Exception

System.SystemException11異常處理

SystemException不向Exception添加新功能。此類是作為一種方法提供的,用于區(qū)分系統(tǒng)定義的異常和應(yīng)用程序定義的異常。SystemException不提供導(dǎo)致Exception原因的信息。不建議捕捉和實例化SystemException。大多數(shù)情況下都不應(yīng)引發(fā)此類的實例,在應(yīng)用程序中引發(fā)該異常不是好的編程做法。如果需要實例化該類,則應(yīng)將描述錯誤的可讀消息傳遞給其構(gòu)造函數(shù)。4.3SystemException類11異常處理4.4ApplicationException類發(fā)生非致命應(yīng)用程序錯誤時引發(fā)的異常。命名空間:System程序集:mscorlib(在mscorlib.dll中)語法[SerializableAttribute][ComVisibleAttribute(true)]publicclassApplicationException:Exception繼承層次結(jié)構(gòu)System.ObjectSystem.ExceptionSystem.ApplicationException11異常處理

用戶應(yīng)用程序(不是公共語言運(yùn)行時)引發(fā)從ApplicationException類派生的自定義異常。ApplicationException類區(qū)分應(yīng)用程序定義的異常與系統(tǒng)定義的異常。應(yīng)從Exception類派生自定義異常,非從ApplicationException類派生。4.4ApplicationException類11異常處理5、異常設(shè)計準(zhǔn)則異常是報告錯誤的標(biāo)準(zhǔn)機(jī)制。應(yīng)用程序和庫不應(yīng)使用返回代碼來傳遞錯誤信息。異常的采用增進(jìn)了框架設(shè)計的一致性,允許無返回類型的成員(如構(gòu)造函數(shù))報告錯誤。異常還允許程序處理錯誤或根據(jù)需要終止運(yùn)行。默認(rèn)行為是在應(yīng)用程序不處理引發(fā)的異常時,終止應(yīng)用程序。11異常處理5.1異常拋出當(dāng)某個成員無法成功執(zhí)行它應(yīng)執(zhí)行的操作時,將會拋出異常。這稱為“執(zhí)行失敗”。下列準(zhǔn)則可幫助確保在適當(dāng)時拋出異常:不要返回錯誤代碼。異常是報告框架中錯誤的主要手段。通過拋出異常來報告執(zhí)行故障。如果某一成員無法按預(yù)期方式成功執(zhí)行,則應(yīng)將這種情況視為一個執(zhí)行故障并拋出一個異常。11異常處理

如果代碼遇到繼續(xù)執(zhí)行則不安全的情況,應(yīng)考慮通過調(diào)用System.Environment.FailFast(System.String)來終止進(jìn)程,而不是拋出異常。盡可能不對正??刂屏魇褂卯惓?。除了系統(tǒng)故障及可能導(dǎo)致爭用狀態(tài)的操作之外,框架設(shè)計人員還應(yīng)設(shè)計一些API以便用戶可以編寫不拋出異常的代碼。例如,可以提供一種在調(diào)用成員之前檢查前提條件的方法,以便用戶可以編寫不拋出異常的代碼。5.1異常拋出11異常處理

下面的代碼示例演示如何進(jìn)行測試以防止在消息字符串為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異常處理

考慮拋出異常的性能影響。記錄公共可調(diào)用的成員因成員協(xié)定沖突(而不是系統(tǒng)故障)而拋出的所有異常,并將這些異常視為協(xié)定的一部分。包含在協(xié)定中的異常不應(yīng)從一個版本更改到下一個版本。不要包含可以根據(jù)某一選項拋出或不拋出異常的公共成員。不要包含將異常作為返回值或輸出參數(shù)返回的公共成員。5.1異常拋出11異常處理

考慮使用異常生成器方法。從不同的位置拋出同一異常會經(jīng)常發(fā)生。為了避免代碼膨脹,請使用幫助器方法創(chuàng)建異常并初始化其屬性。避免從finally塊中顯式拋出異常??梢越邮芤蛘{(diào)用拋出異常的方法而隱式拋出的異常。5.1異常拋出11異常處理選擇要拋出的正確異常類型下列設(shè)計準(zhǔn)則可確保正確地使用現(xiàn)有異常,并在適當(dāng)?shù)臅r候創(chuàng)建對庫有價值的新異常??紤]引發(fā)System命名空間中的現(xiàn)有異常,而不是創(chuàng)建自定義異常類型。如果錯誤狀態(tài)可以通過不同于現(xiàn)有任何其他異常的方法以編程方式進(jìn)行處理,則要創(chuàng)建并拋出自定義異常。否則,拋出一個現(xiàn)有異常。不要只是為了獲得異常而創(chuàng)建和拋出新異常。11異常處理

拋出適當(dāng)?shù)淖罹唧w(派生程度最大)的異常。例如,如果某方法收到一個null(在VisualBasic中為Nothing)參數(shù),則該方法應(yīng)引發(fā)System.ArgumentNullException,而不是引發(fā)該異常的基類型System.ArgumentException。選擇要拋出的正確異常類型11異常處理5.2異常處理下面的準(zhǔn)則有助于確保庫正確處理異常。不要通過在框架代碼或程序中捕捉非特定異常(如System.Exception、System.SystemException等)來處理錯誤。如果捕捉異常是為了再次引發(fā)或傳輸給其他線程,則可以捕捉這些異常。下面的代碼示例演示的異常處理是不正確的。11異常處理

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

如果捕捉異常是為了傳輸異常,則不要排除任何特殊異常。只捕捉能夠合法處理的異常,而不要在catch子句中創(chuàng)建特殊異常的列表。在非特定異常處理程序中,不能處理的異常不應(yīng)視為特殊處理的特殊情況。下面的代碼示例演示對以再次引發(fā)為目的特殊異常進(jìn)行的不正確測試。5.2異常處理11異常處理

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

如果了解特定異常在給定上下文中引發(fā)的條件,請考慮捕捉這些異常。應(yīng)該只捕捉可以從中恢復(fù)的異常。例如,嘗試打開不存在的文件而導(dǎo)致的

可以由應(yīng)用程序處理,因為應(yīng)用程序可以將問題傳達(dá)給用戶,并允許用戶指定其他文件名或創(chuàng)建該文件。如打開文件的請求會生成ExecutionEngineException,則不應(yīng)該處理該請求,因為沒有任何把握可以了解該異常的基礎(chǔ)原因,應(yīng)用程序也無法確保繼續(xù)執(zhí)行是安全的。不要過多使用catch。通常應(yīng)允許異常在調(diào)用堆棧中往上傳播。捕捉無法合法處理的異常會隱藏關(guān)鍵的調(diào)試信息。5.2異常處理11異常處理

使用try-finally并避免將try-catch用于清理代碼。書寫規(guī)范的異常代碼中,try-finally比try-catch更為常用使用catch子句是為了允許處理異常(例如,通過紀(jì)錄非致命錯誤)無論是否拋出了異常,使用finally子句即可執(zhí)行清理代碼如果分配了昂貴或有限的資源(如數(shù)據(jù)庫連接或流),則應(yīng)將釋放這些資源的代碼放置在finally塊中。捕捉并再次拋出異常時,優(yōu)先使用空拋出。這是保留異常調(diào)用堆棧的最佳方式。不要使用無參數(shù)catch塊來處理不符合CLS的異常(不是從System.Exception派生的異常)。5.2異常處理11異常處理5.3捕捉和拋出標(biāo)準(zhǔn)異常類型下面的準(zhǔn)則介紹.NETFramework所提供的某些最常用異常的最佳做法。Exception和SystemException不要拋出System.Exception或System.SystemException不要在框架代碼中捕捉System.Exception或System.SystemException,除非打算再次拋出。避免捕捉System.Exception或System.SystemException,在頂級異常處理程序中除外。11異常處理

ApplicationException一定要從T:System.Exception類而不是T:System.ApplicationException類派生自定義異常。最初考慮自定義異常應(yīng)該從ApplicationException類派生

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論