雜談try-catch-finally異常處置。本站提示廣大學習愛好者:(雜談try-catch-finally異常處置)文章只能為提供參考,不一定能成為您想要的結果。以下是雜談try-catch-finally異常處置正文
相干浏覽:再談異常處置try catch finally
1. 媒介
比來這段時光正開辟一個商號治理體系,這個項目定位於給中小型商號應用的軟件體系。簡略的說,它處置商品的進貨,發賣,退貨等功效。軟件雖小,五髒俱全,外面觸及的技巧跟年夜型運用軟件其實差異也不年夜,個中有加密、數據拜訪、異常處置、日記、驗證、ORM、依附注入等。
本篇文章重要引見C#說話的異常處置方面的內容,個中包括的重要內容:
•甚麼是異常?異常的特色?
•異常處置的基本常識。
•激發和捕獲異常的處置原則。
•防止與異常相干的機能成績的兩種設計形式。
•微軟企業庫異常處置模塊。
2. 異常概述
•在運用法式碰到異常情形(如被零除情形或內存缺乏正告)時,就會發生異常。
•在能夠激發異常的語句四周應用 try 塊。
•try 塊中產生異常後,掌握流會立刻跳轉到聯系關系的異常處置法式(假如存在)。
•假如給定異常沒有異常處置法式,則法式將停滯履行,並顯示一條毛病新聞。
•假如 catch 塊界說了一個異常變量,則可使用它來獲得有關所產生異常的類型的更多信息。
•能夠招致異常的操作經由過程 try 症結字來履行。
•異常處置法式是在異常產生時履行的代碼塊。在 C# 中,catch 症結字用於界說異常處置法式。
•法式可使用 throw 症結字顯式地激發異常。
•異常對象包括有關毛病的具體信息,好比挪用客棧的狀況和有關毛病的文本解釋。
•即便激發了異常,finally 塊中的代碼也會履行,從而使法式可以釋放資本。
3. 異常處置基本常識
3.1. 若何:應用 Try/Catch 塊捕獲異常
將能夠激發異常的代碼節放在 Try 塊中,而將處置異常的代碼放在 Catch 塊中。Catch 塊是一系列以症結字 catch 開首的語句,語句後跟異常類型和要履行的操作。
上面的代碼示例應用 Try/Catch 塊捕獲能夠的異常。Main 辦法包括帶有 StreamReader 語句的 Try 塊,該語句翻開名為 data.txt 的數據文件並從該文件寫入字符串。Try 塊前面是 Catch 塊,該塊捕獲 Try 塊發生的任何異常。
using System; using System.IO; using System.Security.Permissions; // Security permission request. [assembly:FileIOPermissionAttribute(SecurityAction.RequestMinimum, All = @"c:\data.txt")] public class ProcessFile { public static void Main() { try { StreamReader sr = File.OpenText("data.txt"); Console.WriteLine("The first line of this file is {0}", sr.ReadLine()); } catch(Exception e) { Console.WriteLine("An error occurred: '{0}'", e); } } }
3.2. 若何:在 Catch 塊中應用特定異常
產生異常時,異常沿客棧向上傳遞,每一個 Catch 塊都無機會處置它。Catch 語句的次序很主要。將針對特定異常的 Catch 塊放在慣例異常 Catch 塊的後面,不然編譯器能夠會收回毛病。肯定准確 Catch 塊的辦法是將異常的類型與 Catch 塊中指定的異常稱號停止婚配。假如沒有特定的 Catch 塊,則由能夠存在的慣例 Catch 塊捕獲異常。
上面的代碼示例應用 try/catch 塊捕捉 InvalidCastException。該示例創立一個名為 Employee 的類,它帶有一個屬性:人員級別 (Emlevel)。PromoteEmployee 辦法獲得對象並增長人員級別。將 DateTime 實例傳遞給 PromoteEmployee 辦法時,產生 InvalidCastException。
using System; public class Employee { //Create employee level property. public int Emlevel { get { return(emlevel); } set { emlevel = value; } } int emlevel; } public class Ex13 { public static void PromoteEmployee(Object emp) { //Cast object to Employee. Employee e = (Employee) emp; // Increment employee level. e.Emlevel = e.Emlevel + 1; } public static void Main() { try { Object o = new Employee(); DateTime newyears = new DateTime(2001, 1, 1); //Promote the new employee. PromoteEmployee(o); //Promote DateTime; results in InvalidCastException as newyears is not an employee instance. PromoteEmployee(newyears); } catch (InvalidCastException e) { Console.WriteLine("Error passing data to PromoteEmployee method. " + e); } } }
3.3. 若何:顯式激發異常
可使用 throw 語句顯式激發異常。還可使用 throw 語句再次激發捕捉的異常。較好的編碼做法是,向再次激發的異常添加信息以在調試時供給更多信息。
上面的代碼示例應用 try/catch 塊捕捉能夠的 FileNotFoundException。try 塊前面是 catch 塊,catch 塊捕捉 FileNotFoundException,假如找不到數據文件,則向掌握台寫入新聞。下一條語句是 throw 語句,該語句激發新的 FileNotFoundException 並向該異常添加文本信息。
using System; using System.IO; public class ProcessFile { public static void Main() { FileStream fs = null; try { //Opens a text tile. fs = new FileStream(@"C:\temp\data.txt", FileMode.Open); StreamReader sr = new StreamReader(fs); string line; //A value is read from the file and output to the console. line = sr.ReadLine(); Console.WriteLine(line); } catch(FileNotFoundException e) { Console.WriteLine("[Data File Missing] {0}", e); throw new FileNotFoundException(@"data.txt not in c:\temp directory]",e); } finally { if (fs != null) fs.Close(); } } }
3.4. 若何:應用 Finally 塊
異常產生時,履行將終止,而且掌握交給比來的異常處置法式。這平日意味著不履行願望老是挪用的代碼行。有些資本清算(如封閉文件)必需老是履行,即便有異常產生。為完成這一點,可使用 Finally 塊。Finally 塊老是履行,豈論能否有異常產生。
上面的代碼示例應用 try/catch 塊捕捉 ArgumentOutOfRangeException。Main 辦法創立兩個數組並試圖將一個數組復制到另外一個數組。該操作生成 ArgumentOutOfRangeException,同時毛病被寫入掌握台。Finally 塊履行,豈論復制操作的成果若何。
using System; class ArgumentOutOfRangeExample { static public void Main() { int[] array1={0,0}; int[] array2={0,0}; try { Array.Copy(array1,array2,-1); } catch (ArgumentOutOfRangeException e) { Console.WriteLine("Error: {0}",e); } finally { Console.WriteLine("This statement is always executed."); } } }
4. 異常設計原則
4.1. 異常激發
•不要前往毛病代碼。異常是申報框架中的毛病的重要手腕。
•盡量纰謬正常掌握流應用異常。除體系毛病及能夠招致爭用狀況的操作以外,框架設計人員還應設計一些 API 以便用戶可以編寫不激發異常的代碼。例如,可以供給一種在挪用成員之前檢討條件前提的辦法,以便用戶可以編寫不激發異常的代碼。
•不要包括可以依據某一選項激發或不激發異常的公共成員。
•不要包括將異常作為前往值或輸入參數前往的公共成員。
•斟酌應用異常生成器辦法。從分歧的地位激發統一異常會常常產生。為了不代碼收縮,請應用贊助器辦法創立異常並初始化其屬性。
•防止從 finally 塊中顯式激發異常。可以接收因挪用激發異常的辦法而隱式激發的異常。
4.2. 異常處置
•不要經由過程在框架代碼中捕獲非特定異常(如 System.Exception、System.SystemException 等)來處置毛病。
•防止經由過程在運用法式代碼中捕獲非特定異常(如 System.Exception、System.SystemException 等)來處置毛病。某些情形下,可以在運用法式中處置毛病,但這類情形極。
•假如捕獲異常是為了傳輸異常,則不要消除任何特別異常。
•假如懂得特定異常在給定高低文中激發的前提,請斟酌捕獲這些異常。
•不要過量應用 catch。平日應許可異常在挪用客棧中往上流傳。
•應用 try-finally 並防止將 try-catch 用於清算代碼。在書寫標准的異常代碼中,try-finally 遠比 try-catch 更加經常使用。
•捕獲並再次激發異常時,首選應用空激發。這是保存異常挪用客棧的最好方法。
•不要應用無參數 catch 塊來處置不相符 CLS 的異常(不是從 System.Exception 派生的異常)。支撐不是從 Exception 派生的異常的說話可以處置這些不相符 CLS 的異常。
5. 兩種設計形式
5.1. Tester-Doer 形式
Doer 部門
public class Doer { public static void ProcessMessage(string message) { if (message == null) { throw new ArgumentNullException("message"); } } } Tester部門 public class Tester { public static void TesterDoer(ICollection<string> messages) { foreach (string message in messages) { if (message != null) { Doer.ProcessMessage(message); } } } }
5.2. TryParse 形式
TryParse 辦法相似於 Parse 辦法,分歧的地方在於 TryParse 辦法在轉換掉敗時不激發異常。
Parse辦法
public void Do() { string s = “a”; double d; try { d = Double.Parse(s); } catch (Exception ex) { d = 0; } }
TryParse辦法
public void TryDo() { string s = "a"; double d; if (double.TryParse(s, out d) == false) { d = 0; } }
6. 微軟企業庫異常處置模塊
6.1. 創立自界說異常包裝類
public class BusinessLayerException : ApplicationException { public BusinessLayerException() : base() { } public BusinessLayerException(string message) : base(message) { } public BusinessLayerException(string message, Exception exception) : base(message, exception) { } protected BusinessLayerException(SerializationInfo info, StreamingContext context) : base(info, context) { } }
6.2. 設置裝備擺設異常處置
<add name="Wrap Policy"> <exceptionTypes> <add type="System.Data.DBConcurrencyException, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" postHandlingAction="ThrowNewException" name="DBConcurrencyException"> <exceptionHandlers> <add exceptionMessage="Wrapped Exception: A recoverable error occurred while attempting to access the database." exceptionMessageResourceType="" wrapExceptionType="ExceptionHandlingQuickStart.BusinessLayer.BusinessLayerException, ExceptionHandlingQuickStart.BusinessLayer" type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.WrapHandler, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling, Version=3.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" name="Wrap Handler" /> </exceptionHandlers> </add> </exceptionTypes> </add>
6.3. 編寫代碼
public bool ProcessWithWrap() { try { this.ProcessB(); } catch(Exception ex) { // Quick Start is configured so that the Wrap Policy will // log the exception and then recommend a rethrow. bool rethrow = ExceptionPolicy.HandleException(ex, "Wrap Policy"); if (rethrow) { throw; } } return true; }
小結
try { //履行的代碼,個中能夠有異常。一旦發明異常,則立刻跳到catch履行。不然不會履行catch外面的內容 }
catch { //除非try外面履行代碼產生了異常,不然這裡的代碼不會履行 }
finally { //不論甚麼情形都邑履行,包含try catch 外面用了return ,可以懂得為只需履行了try或許catch,就必定會履行 finally }