程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 雜談try-catch-finally異常處置

雜談try-catch-finally異常處置

編輯:C#入門知識

雜談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 }

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved