C sharp中的異常用于處理系統(tǒng)級和應(yīng)用程序級的錯誤狀態(tài),它是一種結(jié)構(gòu)化、統(tǒng)一的類型安全的處理機制。c#的異常 機制非常類似于c++的異常處理機制,但是還是有一些重要的區(qū)別:
1,在 C# 中,所有的異常必須由從 System.Exception 派生的類類型的實例來表示。在 C++ 中,可以使用任何類型的任何值表示異常。
2,在 C# 中,利用 finally 塊可編寫在正常執(zhí)行和異常情況下都將執(zhí)行的終止代碼。在 C++ 中,很難在不重復(fù)代碼的情況下編寫這樣的代碼。
3,C# 中,系統(tǒng)級的異常如溢出、被零除和 null 等都對應(yīng)地定義了與其匹配的異常類,并且與應(yīng)用程序級的錯誤狀態(tài)處于同等地位。
1.1 導(dǎo)致異常的原因
可以以兩種不同的方式引發(fā)異常。
· throw 語句(第 ?8.9.5 節(jié))用于立即無條件地引發(fā)異常??刂朴肋h不會到達緊跟在 throw 后面的語句。
· 在執(zhí)行 C# 語句和表達式的過程中,有時會出現(xiàn)一些例外情況,使某些操作無法正常完成,此時就會引發(fā)一個異常。例如,在整數(shù)除法運算(第 ?7.8.2 節(jié))中,如果分母為零,則會引發(fā) System.DivideByZeroException。有關(guān)可能以此方式引發(fā)的各種異常的列表,請參見第 ?16.4 節(jié)。
1.2 System.Exception 類
System.Exception 類是所有異常的基類型。此類具有一些所有異常共享的值得注意的屬性:
· Message 是 string 類型的一個只讀屬性,它包含關(guān)于所發(fā)生異常的原因的描述(易于人工閱讀)。
· InnerException 是 Exception 類型的一個只讀屬性。如果它的值不是 null,則它所引用的是導(dǎo)致了當(dāng)前異常的那個異常,即表示當(dāng)前異常是在處理那個 InnerException 的 catch 塊中被引發(fā)的。否則,它的值為 null,則表示該異常不是由另一個異常引發(fā)的。以這種方式鏈接在一起的異常對象的數(shù)目可以是任意的。
這些屬性的值可以在調(diào)用 System.Exception 的實例構(gòu)造函數(shù)時指定。
1.3 異常的處理方式
發(fā)生異常時,系統(tǒng)將搜索可以處理該異常的最近的 catch 子句(根據(jù)該異常的運行時類型來確定)。首先,搜索當(dāng)前的方法以查找一個詞法上包含著它的 try 語句,并按順序考察與該 try 語句相關(guān)聯(lián)的各個 catch 子句。如果上述操作失敗,則在調(diào)用了當(dāng)前方法的方法中,搜索在詞法上包含著當(dāng)前方法調(diào)用代碼位置的 try 語句。此搜索將一直進行下去,直到找到可以處理當(dāng)前異常的 catch 子句(該子句指定一個異常類,它與當(dāng)前引發(fā)該異常的運行時類型屬于同一個類或是該運行時類型所屬類的一個基類)。注意,沒有指定異常類的 catch 子句可以處理任何異常。
找到匹配的 catch 子句后,系統(tǒng)將把控制轉(zhuǎn)移到該 catch 子句的第一條語句。在 catch 子句的執(zhí)行開始前,系統(tǒng)將首先按順序執(zhí)行嵌套在捕捉到該異常的 try 語句里面的所有 try 語句所對應(yīng)的全部 finally 子句。
如果沒有找到匹配的 catch 子句,則發(fā)生下列兩種情況之一:
· 如果對匹配的 catch 子句的搜索到達一個靜態(tài)構(gòu)造函數(shù)(第 ?10.12 節(jié))或靜態(tài)字段初始值設(shè)定項,則在導(dǎo)致調(diào)用該靜態(tài)構(gòu)造函數(shù)的代碼位置引發(fā) System.TypeInitializationException。該 System.TypeInitializationException 的內(nèi)部異常將包含最初引發(fā)的異常。
· 如果對匹配的 catch 子句的搜索到達最初啟動當(dāng)前線程的代碼處,則該線程的執(zhí)行就會終止。此類終止會產(chǎn)生什么影響,應(yīng)由實現(xiàn)來定義。
特別值得注意的是在析構(gòu)函數(shù)執(zhí)行過程中發(fā)生的異常。如果在析構(gòu)函數(shù)執(zhí)行過程中發(fā)生異常且該異常未被捕獲,則將終止該析構(gòu)函數(shù)的執(zhí)行,并調(diào)用它的基類的析構(gòu)函數(shù)(如果有)。如果沒有基類(如 object 類型中的情況),或者如果沒有基類析構(gòu)函數(shù),則該異常將被忽略。
1.1 公共異常類
下列異常由某些 C# 操作引發(fā)。
當(dāng)存儲一個數(shù)組時,如果由于被存儲的元素的實際類型與數(shù)組的實際類型不兼容而導(dǎo)致存儲失敗,就會引發(fā)此異常。
在試圖用零除整數(shù)值時引發(fā)。
在試圖使用小于零或超出數(shù)組界限的下標(biāo)索引數(shù)組時引發(fā)。
當(dāng)從基類型或接口到派生類型的顯式轉(zhuǎn)換在運行時失敗時,就會引發(fā)此異常。
在需要使用引用對象的場合,如果使用 null 引用,就會引發(fā)此異常。
在分配內(nèi)存(通過 new)的嘗試失敗時引發(fā)。
在 checked 上下文中的算術(shù)運算溢出時引發(fā)。
當(dāng)執(zhí)行堆棧由于保存了太多掛起的方法調(diào)用而耗盡時,就會引發(fā)此異常;這通常表明存在非常深或無限的遞歸。
在靜態(tài)構(gòu)造函數(shù)引發(fā)異常并且沒有可以捕捉到它的 catch 子句時引發(fā)。
okay上文的內(nèi)容就是對c#語言規(guī)范中對于異常處理的總結(jié),下面總結(jié)一下我們這些新手經(jīng)常出現(xiàn)的問題,請高手們補充,謝謝!
一、是否缺少 using 指令或程序集引用?
這是我在最近的探索中經(jīng)常遇到的問題,雖然已經(jīng)添加引用了,但是總會提示,很折磨的說,我總結(jié)了兩種較為通常的處理:
1、修改:右擊類文件--屬性--生成操作--將“內(nèi)容”改為“編譯”,然后重新生成,問題解決。
2、另一種情況:項目中存在多個類庫,生成項目時提示 未能找到類型或命名空間名稱“XXXX”(是否缺少 using 指令或程序集引用?) ,找到相應(yīng)類庫中的“引用”文件夾,在其中添加對應(yīng)的dll文件,單獨生成此類庫,若還是提示,則需要查看“引用”中是否有引用其他類庫所生成的dll文件,如果存在,則需要先確保生成該dll文件的類庫可以正常生成,以此類推,最終生成整個項目。
二、try,catch,finally
我是這樣理解的,先執(zhí)行try里面的語句,如果try里面的語句拋出了錯誤,就會被catch捕獲,所以就會中斷try里面語句的執(zhí)行轉(zhuǎn)而執(zhí)行catch里面的語句,如果try里面的語句都執(zhí)行完了也沒有拋出錯誤,那么catch里的語句就沒有機會執(zhí)行了。最后不論try順利運行完畢,還是try拋出了錯誤被catch語句捕獲并執(zhí)行了catch的語句都要接著執(zhí)行finally里面的語句。但是總感覺缺點什么~