C#之異常處理
摘要:
1.什麼是異常?
異常實際上是程式中錯誤導致中斷了正常的指令流的一種事件.
2.異常處理的優點:
觀察前面的程式你會發現大部分精力花在出錯處理上了.只把能夠想到的錯誤考慮到,對以外的情況無法處理,程式可讀性差,出錯返回資訊量太少。
綜...
1.什麼是異常?
異常實際上是程式中錯誤導致中斷了正常的指令流的一種事件.
2.異常處理的優點:

觀察前面的程式你會發現大部分精力花在出錯處理上了.只把能夠想到的錯誤考慮到,對以外的情況無法處理,程式可讀性差,出錯返回資訊量太少。

綜合上面的說法和傳統的方法比較異常的優點:
1.把錯誤程式碼從常規程式碼中分離出來。
2.把錯誤傳播給呼叫堆疊:
M1=>M2=>M3 M3異常 =>M2 =>M1=>...=>Main=>CLR
3. 按錯誤型別和錯誤差別分組。
4. 系統提供了對於一些無法預測的錯誤的捕獲和處理。
5. 克服了傳統方法的錯誤資訊有限的問題。
3.何時使用異常機制?
1.當方法因為自身無法控制的原因而不能完成其任務,
檔案不存在,網路連線無法建立……,
2.處理在方法、類庫、類中丟擲的例外,
如FileInputStream.read產生IOException,
3.在大的專案中採用統一的方式處理例外時,
如編寫一個文書處理器,
4.例外應該是不經常發生但卻可能發生的故障,
一定發生的事件不應該用例外機制來處理,
5.例外處理用於使系統從故障中恢復。
提示資訊/不產生無效的結果/釋放資源。
注意事項:
1.不同的例外處理策略
關鍵性應用(處理所有例外)
實驗軟體(可以忽略許多例外)
2.終止程式會導致資源洩漏,利用例外處理釋放資源。
3.儘可能近地處理例外,這樣程式清晰易讀。
4.能在區域性處理的錯誤不要使用例外機制。
例外機制的處理比正常處理效率低。
簡單的異常例項

異常的分類
只要在程式執行過程中出現錯誤,.NET Framework 就會建立一個 Exception 物件詳細描述此錯誤。在 .NET Framework 中,Exception 為所有異常類的基類。
從 Exception 類派生的異常分為兩種類別:
SystemException \ ApplicationException。

一個例外是由一個物件來代表的,
所有的例外都直接或間接地繼承自Exception類。
注意:
使用者也可以通過繼承已有的例外類來定義自己的例外類,並在程式中使用(利用throw產生或丟擲,catch捕捉並處理)。
常見的異常類
一些常見的 System 異常包括:
ArgumentException:
在呼叫某方法時,傳遞的引數中至少有一個不符合所呼叫方法的引數規範。
ArgumentNullException:
呼叫方法時所傳遞的引數中,至少有一個在任何情況下都不應為 null。
ArgumentOutOfRangeException:
呼叫方法時,如果在傳遞給該方法的引數中至少有一個不為null且不包含有效值時,引發該異常。
ArithmeticException:操作將導致上溢或下溢。
ArrayTypeMismatchException:
當試圖在陣列中儲存型別不正確的元素時引發的異常。
DivideByZeroException:
試圖用零除整數值或十進位制數值時引發的異常。
DllNotFoundException:
當未找到在 DLL 匯入中指定的 DLL 時所引發的異常。
IndexOutOfRangeException:
使用了大於陣列或集合大小的索引。
InsufficientMemoryException:
當檢測到沒有足夠的可用記憶體時引發的異常。無法繼承此類。
InvalidCastException:
因無效型別轉換或顯式轉換引發的異常。
InvalidOperationException:
當方法呼叫對於物件的當前狀態無效時引發的異常。
NotImplementedException:
在無法實現請求的方法或操作時引發的異常。
NotSupportedException:
當呼叫的方法不受支援,或試圖讀取或寫入不支援的流時引發的異常。
NullReferenceException:
在將引用設定為有效例項之前使用了引用的屬性或方法。
OutOfMemoryException:
沒有足夠的記憶體繼續執行程式時引發的異常
OverflowException:
在選中的上下文中的算術運算、型別轉換或轉換操作導致溢位時引發的異常。
FormatException:
引數或運算元格式不正確。
使用:

try語句:異常監視塊
作用:監視該程式碼塊是否有異常發生,若有異常,產生異常物件並丟擲
注意:在該程式碼塊中宣告的變數無法在該塊之外訪問
catch語句:異常處理程式碼塊
作用:捕捉try語句中丟擲的異常,並按照程式碼塊中的語句處理
格式:
catch(異常種類){//處理語句}
catch(異常種類 引用名(一般叫e)){//處理語句}:
注意:
1.每個try語句必須伴隨1-n個catch語句。
2.例外總是由距離產生例外最近的匹配catch程式碼段處理。
3.try-catch可以巢狀使用:
如果沒有相應的例外處理
則例外被交給上一層try程式碼段進行處理。
4.匹配的catch執行完畢後,同級的catch將被忽略。
5.先catch小的再catch老的。
6.整個執行流程中若無catch處理 程式中斷!
7.catch的型別應儘量精確。
8.請注意你呼叫的方法是否有可能丟擲異常。
9.catch中也可能產生異常 會拋給巢狀的上一級處理。
10.處理過的異常可以繼續丟擲 以期通知流程中的所有節點有異常。
catch (Exception e) { throw e; }。
11.try-catch機制不該被用於流程控制,例外情形應該是很稀少的,而不是經常性的。
一定會執行的程式塊---finally
異常處理的統一出口

finally:
1.捕獲例外的最後一步是通過finally語句為例外處理提供一個統一的出口,使得在控制流程轉到程式的其他部分以前,能夠對程式的狀態作統一的管理。
2.無論try所指定的程式塊中是否丟擲例外,也無論catch語句的例外型別是否與所拋棄的例外的型別一致,finally所指定的程式碼都要被執行,它提供了統一的出口。(finally語句與switch中的default語句是不同的!)
3.通常在finally語句中可以進行資源的清除工作,如關閉開啟的檔案、刪除臨時檔案等。
finally和return的關係:
1.當try和catch中有return時,finally仍然會執行;
2.finally是在return後面的表示式運算後執行的(此時並沒有返回運算後的值,而是先把要返回的值儲存起來,不管finally中的程式碼如何修改,返回的值都不會改變,仍然是之前儲存的值),所以函式返回值是在finally執行前確定的;
3.finally中不可以有return,否則語法錯誤
丟擲異常:
throw ExceptionObj;
丟擲異常: 不是出錯產生,而是人為地丟擲
1.任何從Exception派生的類都可以用throw語句丟擲,丟擲例外用來表明程式遇到的錯誤無法正常執行而需要例外處理
throw new MyException(“some infomation”);
2.例外丟擲點後的程式碼在丟擲例外後不再執行
也可以說例外的丟擲終止了程式碼段的執行
自定義異常:不是由系統監測到的異常(下標越界,被0-除等),而是由使用者自己定義的異常.
形如:建議ApplicationException作為父類
class MyException : ApplicationException{….}
注意:
使用者定義的異常同樣要用try--catch捕獲,但必須由使用者自己丟擲
throw new MyException(引數).


1.一般格式:正常程式和出錯處理分離開來

2.把異常傳播給堆疊,沿著被呼叫的順序往前尋找,只要找到符合該異常種類徹底異常處理程式,就交給這部分程式去處理
