[C#] C# 知識回顧 - 學會使用異常

来源:http://www.cnblogs.com/liqingwen/archive/2016/12/20/6193534.html
-Advertisement-
Play Games

學會使用異常 在 C# 中,程式中在運行時出現的錯誤,會不斷在程式中進行傳播,這種機制稱為“異常”。 異常通常由錯誤的代碼引發,並由能夠更正錯誤的代碼進行 catch。 異常可由 .NET 的 CLR 或由程式中的代碼引發。 一旦引發了異常,這個異常將會在調用堆棧中一直向上進行傳播,直到尋找到跟它匹 ...


學會使用異常

  在 C# 中,程式中在運行時出現的錯誤,會不斷在程式中進行傳播,這種機制稱為“異常”。 異常通常由錯誤的代碼引發,並由能夠更正錯誤的代碼進行 catch。 異常可由 .NET 的 CLR 或由程式中的代碼引發。 一旦引發了異常,這個異常將會在調用堆棧中一直向上進行傳播,直到尋找到跟它匹配的 catch 語句。沒有 catch 的異常會由系統提供的預設的異常處理程式進行處理,也就是你經常看到的一個突然造成調試中斷並顯示異常信息的對話框。

  所有的異常,它們都是從 Exception 派生出來的。這些異常的類型,都會包含詳細描述異常的屬性。在這裡我將自定義了一個新的異常類,其實也可以自定義配置異常的屬性(這是可選的),然後我使用 throw 關鍵字顯示引發該對象(即異常)。 

 1         /// <summary>
 2         /// 定義新異常
 3         /// </summary>
 4         class MyException : Exception
 5         {
 6             public MyException(string msg) { }
 7         }
 8 
 9         /// <summary>
10         /// 拋出新定義的異常
11         /// </summary>
12         static void ThrowMyExcetion()
13         {
14             throw new MyException("Sorry, this is test!");
15         }

  

  在引發異常之後,運行時程式會檢查當前語句確定它是否包含在 try 塊中。 如果是的話,就會檢查與該 try 塊相關聯的所有 catch 塊,來確定它們是否能夠 catch 該異常。  catch 塊通常會指定異常類型;如果該 catch 塊的類型與異常或它的基類的相同(或匹配),則該 catch 塊就能夠捕獲並處理。

 1         static void Main(string[] args)
 2         {
 3             try
 4             {
 5                 ThrowMyExcetion();  //直接調用拋出異常的方法
 6             }
 7             catch (MyException e)
 8             {
 9                 Console.WriteLine(e);
10             }
11 
12             Console.Read();
13         }

 

  如果引發異常的語句不在 try 塊中,或者包含該語句的 try 塊沒有匹配的 catch 塊,運行時將檢查調用方法中是否有 try 語句和 catch 塊。 運行時將在調用堆棧中繼續往上搜索相容(或匹配)的 catch 塊。在找到並執行 catch 塊之後,控制權將傳遞給 catch 塊之後的下一個語句。

  一個 try 語句可能包含多個 catch 塊。 將執行第一個能夠處理該異常的 catch 語句;任何後續的 catch 語句都將被忽略,即使它們是相容的也如此。 因此,在任何情況下都應該按照從最具體(或者派生程度最高)到最不具體這一順序排列 catch 塊。 例如:

 1         static void Main(string[] args)
 2         {
 3             StreamWriter sw = null;
 4 
 5             try
 6             {
 7                 sw = new StreamWriter(@"C:\book\小二和小三的故事.txt");
 8                 sw.Write("You are 250.");
 9             }
10             catch (FileNotFoundException e)
11             {
12                 //將具體的異常放在第一位
13                 Console.WriteLine(e);
14             }
15             catch (IOException e)
16             {
17                 //將並不具體的放在相對後面的位置
18                 Console.WriteLine(e);
19             }
20             catch (Exception e)
21             {
22                 Console.WriteLine(e);
23             }
24             finally
25             {
26                 if (sw != null)
27                 {
28                     sw.Close();
29                 }
30             }
31 
32             Console.Read();
33         }

 

  執行 catch 塊之前,運行時會檢查 finally 塊。 Finally 塊使程式員能夠清除中止的 try 塊可能遺留下的任何模糊狀態,或者釋放任何外部資源(例如圖形句柄、資料庫連接或文件流),而無需等待運行時中的垃圾回收器終結這些對象。 例如:

 1         static void Main(string[] args)
 2         {
 3             FileStream fs = null;
 4             FileInfo fi = new FileInfo(@"小二和小三的故事.txt");
 5 
 6             try
 7             {
 8                 fs = fi.OpenWrite();
 9                 fs.WriteByte(0);
10             }
11             finally
12             {
13                 //記住哦,如果你忘記 close,將會引發 IO 異常!
14                 //if (fs != null)
15                 //{
16                 //    fs.Close();
17                 //}
18             }
19 
20             try
21             {
22                 fs = fi.OpenWrite();
23                 fs.WriteByte(1);
24                 Console.WriteLine("OK!");
25             }
26             catch (IOException e)
27             {
28                 Console.WriteLine("Fail!");
29             }
30 
31             Console.Read();
32         }

  “Fail!”,這是因為上面註釋了需要關閉文件流的語句,你可以嘗試下去掉註釋看看結果,記住哦,IO 操作都應該在結束時釋放資源。 

  如果 WriteByte(0)(第9行) 引發了異常,那麼在沒有調用 fs.Close() 的情況下,你在第二個 try 塊中嘗試重新 OpenWrit() 的代碼就會失敗,因為此時文件會保持鎖定狀態。 假如你取消註釋,由於會執行 finally 塊(即使已引發異常),使得可以正確地關閉文件,從而避免再次引發異常。

  如果在引發異常之後沒有在調用堆棧上找到相匹配的 catch 塊,則會可能會出現下麵的情況:

  • 如果異常出現在析構函數中,則中止該析構函數並調用基類的析構函數(如果有)。

  • 如果調用堆棧包含靜態構造函數或靜態欄位初始值設定項,則會引發 TypeInitializationException,並將原始異常分配給新異常的 InnerException 屬性。

  • 如果到達線程的開頭,將會終止線程。

 

C# 基礎回顧系列 

  《C# 知識回顧 - 序列化

  《C# 知識回顧 - 表達式樹 Expression Trees

  《C# 知識回顧 - 特性 Attribute》、《剖析 AssemblyInfo.cs - 瞭解常用的特性 Attribute

  《C# 知識回顧 - 委托 delegate》、《C# 知識回顧 - 委托 delegate (續)

  《C# 知識回顧 - 事件入門》、《C# 知識回顧 - Event 事件

  《string 與 String,大 S 與小 S 之間沒有什麼不可言說的秘密

  《C# 知識回顧 - 異常介紹

 

 


【博主】反骨仔

【出處】http://www.cnblogs.com/liqingwen/p/6193534.html

【參考】微軟官方文檔

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Task為.NET提供了基於任務的非同步模式,它不是線程,它運行線上程池的線程上。本著開源的精神, 本文以解讀基於.NET4.5 Task源碼的方式來揭秘Task的實現原理。 Task的創建 Task的創建方式主要有2種:Task.Run 和Task.Factory.StartNew,各自有不同的ov ...
  • 最近悟出來一個道理,在這兒分享給大家:學歷代表你的過去,能力代表你的現在,學習代表你的將來。 十年河東十年河西,莫欺少年窮 學無止境,精益求精 本節探討如何在VS2012中使用Log4Net 1、首先在項目中添加Nuget程式包... 2、然後在NuGet窗體中搜索Log4Net,然後點擊安裝<安裝 ...
  • 學會處理異常 你可以使用 try 塊來對你覺得可能會出現異常的代碼進行分區。 其中,與之關聯的 catch 塊可用於處理任何異常情況。 一個包含代碼的 finally 塊,無論 try 塊中是否在運行時引發異常(例如,釋放在 try 塊中分配的資源),這些 finally 塊的代碼都會運行。 這些“ ...
  • 1、企業系統集成的時候,大量的欄位是很麻煩處理的,用Format 的方式可快速處理 string sql = @"SELECT * FROM table WHERE TASKID='" + taskid + "'"; DataTable dt = DBUtil.Query(sql).Tables[0 ...
  • /// /// Clones the control. /// /// The source element. /// The dest element. public void CloneControl(UIElement sourceElement, UIElement destElement.... ...
  • 最近又重新整理一下log4net日誌的配置,現在記錄一下流程和一些遇到的問題,以備後續使用,具體的配置參數等信息.此文無,見諒! 1. 下載log4net.dll文件(網上很多,隨便找一個!) 2. 項目中引用此dll 3. appconfig中配置log4net(具體配置方案有很多例子.) 4.  ...
  • Smobiler是一個在VS環境中使用.Net語言來開發APP的開發平臺,也許比Xamarin更方便 ...
  • 前言 solr排除查詢也就是我們在資料庫和程式中經常處理的不等於,solr的語法是在定語前加【-】。、 從Solr控制台 從solr控制台看下排除查詢的url, 也可以在構建url查詢時自己添加篩選條件 ...
一周排行
    -Advertisement-
    Play Games
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...