異常是指成員沒有完成它的名稱所宣稱的行動。c#
如 FileStream 的 方法裏有 Read,Write,等等(行動成員一般用動詞表示)。當行動成員不能完成任務時,就應拋出異常。安全
若是代碼須要執行通常性的資源清理操做,須要從異常中恢復,或者二者都須要,就能夠放到 try 塊中。負責清理的代碼應該放到一個 finally 塊中。try 塊還可包含也許會拋出異常的代碼。負責異常恢復的代碼應放到一個或多個 catch 塊中。針對應用程序能從中安全恢復的每一種異常,都應該建立一個 catch 塊。一個 try 塊至少要有一個關聯的 catch 塊或 finally 塊,單獨一個 try 塊沒有意義,C# 也不容許。ide
開發人員有時不知道應該在一個 try 塊中放入多少代碼。這具體取決於狀態管理。若是在一個 try 塊中執行多個可能拋出同一個異常類型的操做,但不一樣的操做有不一樣的異常恢復措施,就應該將每一個操做都放到它本身的 try 塊中,這樣才能正確地恢復狀態。spa
catch 塊包含的是響應一個異常須要執行的代碼。一個 try 塊 能夠關聯0個或多個 catch 塊。若是try 塊中的代碼沒有形成異常的拋出,CLR 永遠不會執行它的 catch塊。線程將跳過全部 catch 塊,直接直觀性 finally 塊(若是有的話)。.net
catch 關鍵字後的圓括號中的表達式稱爲捕捉類型。c# 要求捕捉類型必須是 System.Exception 或者它的派生類型。例如處理 InvalidOperationException 異常和 IOException 的 catch 塊。最後一個 catch 塊沒有指定捕捉類型,能處理除了前面的 catch塊指定的以外的其餘全部異常;這至關於捕捉 System.Exception。線程
CLR 自上而下搜索匹配的 catch 塊,因此應該將較具體的異常放在頂部。也就是說,首先出現的是派生程度最大的異常類型,接着是它們的基類型(若是有的話),最後是System.Exception。3d
在 try 塊的代碼(或者從 try 塊調用的任何方法)中拋出異常,CLR 將搜索捕捉類型與拋出的異常相同(或者是它的基類)的 catch 塊。若是沒有任何捕捉類型與拋出的異常匹配,CLR會去調用棧更高的一層搜索與異常匹配的捕捉類型。若是都到了調用棧的頂部,仍是沒有找到匹配的 catch 塊就會發生未處理的異常。一旦 CRL 找到匹配的 catch 塊,就會執行「內層」全部的 finally 塊中的代碼。所謂「內層 finally 塊」 是指從拋出異常的 try 塊開始,到匹配異常的 catch 塊之間全部的 finally 塊。注意,匹配異常的那個 catch 塊所關聯的 finally 塊還沒有執行,該 finally 塊中的代碼一直要等到這個 catch 塊中的代碼執行完畢才執行。code
static void Main(string[] args) { /* 嵌套try塊 * try * { * //A * try * { * //B * } * catch * { * //C * } * finally * { * //D * } * //E * } * catch * { ... } * finally * { ... } * * 拋出異常在:內層A,E處由外層catch塊捕獲,並執行外層finally * 拋出異常在:內層B處,且有一合適內層catch捕獲,執行內層finally,後執行E處 * 拋出異常在:內層B處,但內層catch塊沒有合適處理程序,執行內層finally,搜索外層catch,找合適的,執行外層finally,此時不會執行E * 拋出異常在:內層C處,退出內層catch塊,執行內層finally,搜索外層catch,找到合適,執行外層finally * 拋出異常在:內層D處,退出內層finally塊,搜索外層catch,找到合適,執行外層finally */ /* 使用嵌套塊的緣由: * 1.修改所拋出的異常類型 * 2.在代碼的不一樣地方處理不一樣類型的異常 */ }
以上代碼轉至:C#嵌套try塊工做原理對象
全部內層 finally 塊執行完畢後,匹配異常的那個 catch 塊中的代碼纔開始執行。catch 塊中的代碼一般執行一些對異常進行處理的操做。在 catch 塊的末尾,咱們有如下三個選擇。blog
一、從新拋出相同的異常,向調用棧高一層的代碼通知該異常的發生。
二、拋出一個不一樣的異常,向調用棧高一層的代碼提供更豐富的異常信息。
三、讓現成從 catch 塊的底部退出。(非終止線程,而是說執行正常地「貫穿」 catch 塊的底部,並執行匹配的 finally 塊)
選擇前兩種技術將拋出異常,CLR 的行爲和以前說的同樣:回溯調用棧,查找捕捉類型與拋出的異常的類型匹配的 catch 塊。
選擇後一種技術,當線程從 catch 塊的底部退出後,它將當即執行包含在 finally 塊(這個纔是與 catch 關聯的 finally 塊,也就是常說的 try-catch-finally 中的finally)中的代碼。finally 塊的全部代碼執行完畢後,線程退出 finally 塊,執行緊跟 finall 塊以後的語句。若是不存在 finally 塊,線程將從最後一個 catch 塊以後的語句開始執行。
c# 容許在捕捉類型後置頂一個變量。如 ArgumentNullException e,可經過 e 查看異常的具體信息。雖然這個對象能夠修改,但最好不要這麼作,而應把它當成只讀。