C#進(jìn)階-異常處理

什么是異常?

異常實(shí)際上是程序中錯(cuò)誤導(dǎo)致中斷了正常的指令流的一種事件.

異常處理的優(yōu)點(diǎn):

沒有處理錯(cuò)誤的程序:

?read-file {

?????openTheFile;

?????determine its size;

?????allocate that much memory;

?????closeTheFile; ?

}

以常規(guī)方法處理錯(cuò)誤

openFiles;

if (theFilesOpen) {

??determine the lenth of the file;

??if (gotTheFileLength){

????allocate that much memory;

????if (gotEnoughMemory) {

???????read the file into memory;

???????if (readFailed) errorCode=-1;

???????else errorCode=1;

????}else ?errorCode=-3;

??}else errorCode=-5 ;

?}else errorCode=-5;

觀察前面的程序你會發(fā)現(xiàn)大部分精力花在出錯(cuò)處理上了.

只把能夠想到的錯(cuò)誤考慮到,對以外的情況無法處理

程序可讀性差

出錯(cuò)返回信息量太少

用異常的形式處理錯(cuò)誤

read-File;

{ try {

????openTheFile;

????determine its size;

????allocate that much memory;

????closeTheFile;

?}catch(fileopenFailed) { dosomething; }

??catch(sizeDetermineFailed) {dosomething;}

??catch(memoryAllocateFailed){ dosomething;}

??catch(readFailed){ dosomething;}

??catch(fileCloseFailed) { dosomething; }

??catch(Exception) {dosomething;} ?//其它未考慮到的錯(cuò)誤

綜合上面的說法和傳統(tǒng)的方法比較異常的優(yōu)點(diǎn):

1.把錯(cuò)誤代碼從常規(guī)代碼中分離出來

2.把錯(cuò)誤傳播給調(diào)用堆棧

M1=>M2=>M3? M3異常 =>M2 =>M1=>...=>Main=>CLR

3. 按錯(cuò)誤類型和錯(cuò)誤差別分組

4. 系統(tǒng)提供了對于一些無法預(yù)測的錯(cuò)誤的捕獲和處理

5. 克服了傳統(tǒng)方法的錯(cuò)誤信息有限的問題

什么情況下使用例外機(jī)制?

1.當(dāng)方法因?yàn)樽陨頍o法控制的原因而不能完成其任務(wù)

???? 文件不存在聂儒,網(wǎng)絡(luò)連接無法建立……

2.處理在方法、類庫、類中拋出的例外

???? 如FileInputStream.read產(chǎn)生IOException

3.在大的項(xiàng)目中采用統(tǒng)一的方式處理例外時(shí)

???? 如編寫一個(gè)文字處理器

4.例外應(yīng)該是不經(jīng)常發(fā)生但卻可能發(fā)生的故障

???? 一定發(fā)生的事件不應(yīng)該用例外機(jī)制來處理

5.例外處理用于使系統(tǒng)從故障中恢復(fù)

???? 提示信息/不產(chǎn)生無效的結(jié)果/釋放資源

注意事項(xiàng):

1.不同的例外處理策略

???? 關(guān)鍵性應(yīng)用(處理所有例外)

???? 實(shí)驗(yàn)軟件(可以忽略許多例外)

2.終止程序會導(dǎo)致資源泄漏岖沛,利用例外處理釋放資源

3.盡可能近地處理例外辨泳,這樣程序清晰易讀

4.能在局部處理的錯(cuò)誤不要使用例外機(jī)制

???? 例外機(jī)制的處理比正常處理效率低

異常的分類:

只要在程序執(zhí)行過程中出現(xiàn)錯(cuò)誤恕出,.NET Framework 就會創(chuàng)建一個(gè) Exception 對象詳細(xì)描述此錯(cuò)誤。在 .NET Framework 中喊崖,Exception 為所有異常類的基類。

從 Exception 類派生的異常分為兩種類別:

SystemException \ ApplicationException雇逞。

一個(gè)例外是由一個(gè)對象來代表的

所有的例外都直接或間接地繼承自Exception類

注意:

用戶也可以通過繼承已有的例外類來定義自己的例外類荤懂,并在程序中使用(利用throw產(chǎn)生或拋出,catch捕捉并處理)塘砸。

一些常見的 System 異常包括:

ArgumentException:

在調(diào)用某方法時(shí)节仿,傳遞的參數(shù)中至少有一個(gè)不符合所調(diào)用方法的參數(shù)規(guī)范。

ArgumentNullException:

調(diào)用方法時(shí)所傳遞的參數(shù)中掉蔬,至少有一個(gè)在任何情況下都不應(yīng)為 null廊宪。

ArgumentOutOfRangeException:

調(diào)用方法時(shí),如果在傳遞給該方法的參數(shù)中至少有一個(gè)不為null且不包含有效值時(shí)女轿,引發(fā)該異常箭启。

ArithmeticException:操作將導(dǎo)致上溢或下溢。

ArrayTypeMismatchException:

當(dāng)試圖在數(shù)組中存儲類型不正確的元素時(shí)引發(fā)的異常蛉迹。

DivideByZeroException:

試圖用零除整數(shù)值或十進(jìn)制數(shù)值時(shí)引發(fā)的異常傅寡。

DllNotFoundException:

當(dāng)未找到在 DLL 導(dǎo)入中指定的 DLL 時(shí)所引發(fā)的異常。

IndexOutOfRangeException:

使用了大于數(shù)組或集合大小的索引。

InsufficientMemoryException:

當(dāng)檢測到?jīng)]有足夠的可用內(nèi)存時(shí)引發(fā)的異常荐操。無法繼承此類大猛。

InvalidCastException:

因無效類型轉(zhuǎn)換或顯式轉(zhuǎn)換引發(fā)的異常。

InvalidOperationException:

當(dāng)方法調(diào)用對于對象的當(dāng)前狀態(tài)無效時(shí)引發(fā)的異常淀零。

NotImplementedException:

在無法實(shí)現(xiàn)請求的方法或操作時(shí)引發(fā)的異常挽绩。

NotSupportedException:

當(dāng)調(diào)用的方法不受支持,或試圖讀取或?qū)懭氩恢С值牧鲿r(shí)引發(fā)的異常驾中。

NullReferenceException:

在將引用設(shè)置為有效實(shí)例之前使用了引用的屬性或方法唉堪。

OutOfMemoryException:

沒有足夠的內(nèi)存繼續(xù)執(zhí)行程序時(shí)引發(fā)的異常

OverflowException:

在選中的上下文中的算術(shù)運(yùn)算、類型轉(zhuǎn)換或轉(zhuǎn)換操作導(dǎo)致溢出時(shí)引發(fā)的異常肩民。

FormatException:

參數(shù)或操作數(shù)格式不正確唠亚。

捕捉異常:

捕獲并處理異常

try ?

{

??//接受監(jiān)視的程序塊,在此區(qū)域內(nèi)發(fā)生

??//的異常,由catch中指定的程序處理;

}

// 不能有其它語句分隔

catch(要處理的異常種類和標(biāo)識符)

{

??//處理異常;

}

catch(要處理的異常種類和標(biāo)識符)

{

??//處理異常;

}

try語句:異常監(jiān)視塊


作用:監(jiān)視該代碼塊是否有異常發(fā)生,若有異常持痰,產(chǎn)生異常對象并拋出

注意:在該代碼塊中聲明的變量無法在該塊之外訪問

catch語句:異常處理代碼塊

作用:捕捉try語句中拋出的異常灶搜,并按照代碼塊中的語句處理

格式:

catch(異常種類){//處理語句}

catch(異常種類 引用名(一般叫e)){//處理語句}:

注意:

1.每個(gè)try語句必須伴隨1-n個(gè)catch語句

2.例外總是由距離產(chǎn)生例外最近的匹配catch代碼段處理

3.try-catch可以嵌套使用:

如果沒有相應(yīng)的例外處理

???? 則例外被交給上一層try代碼段進(jìn)行處理

4.匹配的catch執(zhí)行完畢后,同級的catch將被忽略

5.先catch小的再catch老的

6.整個(gè)執(zhí)行流程中若無catch處理 程序中斷工窍!

7.catch的類型應(yīng)盡量精確

8.請注意你調(diào)用的方法是否有可能拋出異常

9.catch中也可能產(chǎn)生異常 會拋給嵌套的上一級處理

10.處理過的異掣盥簦可以繼續(xù)拋出 以期通知流程中的所有節(jié)點(diǎn)有異常

catch (Exception e) { throw e; }

11.try-catch機(jī)制不該被用于流程控制,例外情形應(yīng)該是很稀少的患雏,而不是經(jīng)常性的

編寫程序,包含四種異常

算術(shù)異常, 字符串越界,數(shù)組越界,格式異常(字符串轉(zhuǎn)數(shù)字)

觀察輸出信息:

每個(gè)異常對象可以直接給出信息

一定會執(zhí)行的程序塊---finally

異常處理的統(tǒng)一出口

try

{

? //常規(guī)的代碼;

}

catch()

{

//處理異常

}

finally

{

? //不論發(fā)生什么異常(或者不發(fā)生任何異常),都要執(zhí)行的部分;

}

finally:

?????1.捕獲例外的最后一步是通過finally語句為例外處理提供一個(gè)統(tǒng)一的出口鹏溯,使得在控制流程轉(zhuǎn)到程序的其他部分以前,能夠?qū)Τ绦虻臓顟B(tài)作統(tǒng)一的管理淹仑。

?????2.無論try所指定的程序塊中是否拋出例外丙挽,也無論catch語句的例外類型是否與所拋棄的例外的類型一致,finally所指定的代碼都要被執(zhí)行匀借,它提供了統(tǒng)一的出口颜阐。(finally語句與switch中的default語句是不同的!)

?????3.通常在finally語句中可以進(jìn)行資源的清除工作吓肋,如關(guān)閉打開的文件凳怨、刪除臨時(shí)文件等。

finally和return的關(guān)系:

1.當(dāng)try和catch中有return時(shí)蓬坡,finally仍然會執(zhí)行猿棉;

2.finally是在return后面的表達(dá)式運(yùn)算后執(zhí)行的(此時(shí)并沒有返回運(yùn)算后的值,而是先把要返回的值保存起來屑咳,不管finally中的代碼如何修改萨赁,返回的值都不會改變,仍然是之前保存的值)兆龙,所以函數(shù)返回值是在finally執(zhí)行前確定的杖爽;

3.finally中不可以有return敲董,否則語法錯(cuò)誤

拋出異常:

throw ExceptionObj;

拋出異常: 不是出錯(cuò)產(chǎn)生,而是人為地拋出

1.任何從Exception派生的類都可以用throw語句拋出,拋出例外用來表明程序遇到的錯(cuò)誤無法正常執(zhí)行而需要例外處理

throw new MyException(“some infomation”);

2.例外拋出點(diǎn)后的代碼在拋出例外后不再執(zhí)行

也可以說例外的拋出終止了代碼段的執(zhí)行

自定義異常:

不是由系統(tǒng)監(jiān)測到的異常(下標(biāo)越界,被0-除等),而是由用戶自己定義的異常.

形如:建議ApplicationException作為父類

class MyException : ApplicationException{….}

注意:

用戶定義的異常同樣要用try--catch捕獲,但必須由用戶自己拋出

throw new MyException(參數(shù)).

例:

計(jì)算兩個(gè)數(shù)之和,當(dāng)任意一個(gè)數(shù)超出范圍時(shí),拋出自己的異常

public class NumberRangeException : ApplicationException

{ ?

public NumberRangeException(String msg):base(msg)

{

}

}

public int CalcAnswer(String str1, String str2)

{

????int int1, int2;

????int answer = -1;

????try

????{

?????????int1 = int.Parse(str1);

?????????int2 = int.Parse(str2);

?????????if( (int1 < 10) || (int1 > 20)|| (int2 < 10) || (int2 > 20)))

?????????{

NumberRangeException e = new NumberRangeException("Numbers not within the specified range.");

????????????throw e;

?????????}

?????????answer = int1 + int2;

????}

catch (FormatException e)

{

???? ?Console.WriteLine(e);

????}

????return answer;

}

public void GetAnswer()

{

???String answerStr=null;

???try

???{

????????int answer = CalcAnswer(“12”, “5”);

???}

catch (NumberRangeException e)

{

????????answerStr = e.Message;

???}

???Console.WriteLine(answerStr);

}

1.一般格式:正常程序和出錯(cuò)處理分離開來

try

{

C# statement;

}

catch(ExceptionType1 ExceptionObject)

{

???Exception1 ?handling;

}

catch(ExceptionType2 ExceptionObject)

{

???Exception2 ?handling;

}

finally

{

???final handling;

?? // ?(統(tǒng)一的出口,最終必定要執(zhí)行)

}

2.把異常傳播給堆棧,沿著被調(diào)用的順序往前尋找,只要找到符合該異常種類徹底異常處理程序,就交給這部分程序去處理

3.異澄堪玻可以人為地拋出,用throw new 語句

5.異骋刚可以是系統(tǒng)已經(jīng)定義好的,也可以是用戶自己定義的

5.用戶自己定義的異常一定繼承自Exception類 一般繼承自ApplicationException

異常小結(jié):

1.異常是什么

2.異常怎么分類

3.異常如何捕捉 捕捉有規(guī)則嗎

4.異常在調(diào)用堆棧中怎么傳遞

5.怎么手動拋出一個(gè)異常

6.怎么自定義一個(gè)異常類

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市化焕,隨后出現(xiàn)的幾起案子萄窜,更是在濱河造成了極大的恐慌,老刑警劉巖撒桨,帶你破解...
    沈念sama閱讀 212,080評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件查刻,死亡現(xiàn)場離奇詭異,居然都是意外死亡凤类,警方通過查閱死者的電腦和手機(jī)穗泵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,422評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來谜疤,“玉大人佃延,你說我怎么就攤上這事∫目模” “怎么了履肃?”我有些...
    開封第一講書人閱讀 157,630評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長企锌。 經(jīng)常有香客問我榆浓,道長于未,這世上最難降的妖魔是什么撕攒? 我笑而不...
    開封第一講書人閱讀 56,554評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮烘浦,結(jié)果婚禮上抖坪,老公的妹妹穿的比我還像新娘。我一直安慰自己闷叉,他們只是感情好擦俐,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,662評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著握侧,像睡著了一般蚯瞧。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上品擎,一...
    開封第一講書人閱讀 49,856評論 1 290
  • 那天埋合,我揣著相機(jī)與錄音,去河邊找鬼萄传。 笑死甚颂,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播振诬,決...
    沈念sama閱讀 39,014評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼蹭睡,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了赶么?” 一聲冷哼從身側(cè)響起肩豁,我...
    開封第一講書人閱讀 37,752評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎辫呻,沒想到半個(gè)月后蓖救,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,212評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡印屁,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,541評論 2 327
  • 正文 我和宋清朗相戀三年循捺,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片雄人。...
    茶點(diǎn)故事閱讀 38,687評論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡从橘,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出础钠,到底是詐尸還是另有隱情恰力,我是刑警寧澤,帶...
    沈念sama閱讀 34,347評論 4 331
  • 正文 年R本政府宣布旗吁,位于F島的核電站踩萎,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏很钓。R本人自食惡果不足惜香府,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,973評論 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望码倦。 院中可真熱鬧企孩,春花似錦、人聲如沸袁稽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,777評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽推汽。三九已至补疑,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間歹撒,已是汗流浹背莲组。 一陣腳步聲響...
    開封第一講書人閱讀 32,006評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留栈妆,地道東北人胁编。 一個(gè)月前我還...
    沈念sama閱讀 46,406評論 2 360
  • 正文 我出身青樓厢钧,卻偏偏與公主長得像,于是被迫代替她去往敵國和親嬉橙。 傳聞我的和親對象是個(gè)殘疾皇子早直,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,576評論 2 349

推薦閱讀更多精彩內(nèi)容