程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C >> C語言基礎知識 >> 第七章 異常處理

第七章 異常處理

編輯:C語言基礎知識
第七章   異常處理

    通用語言運行時(CLR)具有的一個很大的優勢為,異常處理是跨語言被標准化的。一個在C#中所引發的異常可以在Visual Basic客戶中得到處理。不再有 HRESULTs  或者 ISupportErrorInfo 接口。
    盡管跨語言異常處理的覆蓋面很廣,但這一章完全集中討論C#異常處理。你稍為改變編譯器的溢出處理行為,接著有趣的事情就開始了:你處理了該異常。要增加更多的手段,隨後引發你所創建的異常。

7.1  校驗(checked)和非校驗(unchecked)語句
    當你執行運算時,有可能會發生計算結果超出結果變量數據類型的有效范圍。這種情況被稱為溢出,依據不同的編程語言,你將被以某種方式通知——或者根本就沒有被通知。(C++程序員聽起來熟悉嗎?)
     那麼,C#如何處理溢出的呢? 要找出其默認行為,請看我在這本書前面提到的階乘的例子。(為了方便其見,前面的例子再次在清單 7.1 中給出)

清單 7.1     計算一個數的階乘

1: using System;
2:
3: class Factorial
4: {
5:  public static void Main(string[] args)
6:  {
7:   long nFactorial = 1;
8:   long nComputeTo = Int64.Parse(args[0]);
9:
10:   long nCurDig = 1;
11:   for (nCurDig=1;nCurDig <= nComputeTo; nCurDig++)
12:    nFactorial *= nCurDig;
13:
14:   Console.WriteLine("{0}! is {1}",nComputeTo, nFactorial);
15:  }
16: }

    當你象這樣使用命令行執行程序時
    factorial 2000

    結果為0,什麼也沒有發生。因此,設想C#默默地處理溢出情況而不明確地警告你是安全的。
     通過給整個應用程序(經編譯器開關)或於語句級允許溢出校驗,你就可以改變這種行為。以下兩節分別解決一種方
案。
7.1.1 給溢出校驗設置編譯器
    如果你想給整個應用程序控制溢出校驗,C#編譯器設置選擇是正是你所要找的。默認地,溢出校驗是禁用的。要明確
地要求它,運行以下編譯器命令:
csc factorial.cs /checked+

    現在當你用2000參數執行應用程序時,CLR通知你溢出異常(見圖 7.1)。

圖 7.1允許了溢出異常,階乘代碼產生了一個異常。

按OK鍵離開對話框揭示了異常信息:
Exception occurred: System.OverflowException
  at Factorial.Main(System.String[])

現在你了解了溢出條件引發了一個 System.OverflowException異常。下一節,在我們完成語法校驗之後,如何捕獲並
處理所出現的異常?
7.1.2語法溢出校驗
如果你不想給整個應用程序允許溢出校驗,僅給某些代碼段允許校驗,你可能會很舒適。對於這種場合,你可能象清
單7.2中顯示的那樣,使用校驗語句。

清單 7.2階乘計算中的溢出校驗

1: using System;
2:
3: class Factorial
4: {
5:  public static void Main(string[] args)
6:  {
7:   long nFactorial = 1;
8:   long nComputeTo = Int64.Parse(args[0]);
9:
10:   long nCurDig = 1;
11:
12:   for (nCurDig=1;nCurDig <= nComputeTo; nCurDig++)
13:    checked { nFactorial *= nCurDig; }
14:
15:   Console.WriteLine("{0}! is {1}",nComputeTo, nFactorial);
16:  }
17: }

甚至就如你運用標志 checked-編譯了該代碼,在第13行中,溢出校驗仍然會對乘法實現檢查。錯誤信息保持一致。

顯示相反行為的語句是非校驗(unchecked )。甚至如果允許了溢出校驗(給編譯器加上checked+標志),被
unchecked 語句所括住的代碼也將不會引發溢出異常:

unchecked
{
nFactorial *= nCurDig;
}
  
    

7.2 異常處理語句
既然你知道了如何產生一個異常(你會發現更多的方法,相信我),仍然存在如何處理它的問題。如果你是一個 C++
WIN32 程序員,肯定熟悉SEH(結構異常處理)。你將從中找到安慰,C#中的命令幾乎是相同的,而且它們也以相似的方
式運作。

The following three sections introduce C#s exception-handling statements:
  以下三節介紹了C#的異常處理語句:

。用 try-catch 捕獲異常
。用try-finally 清除異常
。用try-catch-finally 處理所有的異常

7.2.1 使用 try 和 catch捕獲異常
你肯定會對一件事非常感興趣——不要提示給用戶那令人討厭的異常消息,以便你的應用程序繼續執行。要這樣,你
必須捕獲(處理)該異常。
    這樣使用的語句是try 和 catch。try包含可能會產生異常的語句,而catch處理一個異常,如果有異常存在的話。清
單7.3 用try 和 catch為OverflowException 實現異常處理。

   清單7.3  捕獲由Factorial Calculation引發的OverflowException 異常

1: using System;
2:
3: class Factorial
4: {
5:  public static void Main(string[] args)
6:  {
7:   long nFactorial = 1, nCurDig=1;
8:   long nComputeTo = Int64.Parse(args[0]);
9:
10:   try
11:   {
12:    checked
13:    {
14:     for (;nCurDig <= nComputeTo; nCurDig++)
15:      nFactorial *= nCurDig;
16:    }
17:   }
18:   catch (OverflowException oe)
19:   {
20:    Console.WriteLine("Computing {0} caused an overflow exception", nComputeTo);
21:    return;
22:   }
23:
24:   Console.WriteLine("{0}! is {1}",nComputeTo, nFactorial);
25:  }
26: }

    為了說明清楚,我擴展了某些代碼段,而且我也保證異常是由checked 語句產生的,甚至當你忘記了編譯器設置時。
    正如你所見,異常處理並不麻煩。你所有要做的是:在try語句中包含容易產生異常的代碼,接著捕獲異常,該異常在
這個例子中是OverflowException類型。無論一個異常什麼時候被引發,在catch段裡的代碼會注意進行適當的處理。
    如果你不事先知道哪一種異常會被預期,而仍然想處於安全狀態,簡單地忽略異常的類型。

try
{
...
}
catch
{
...
}

    但是,通過這個途徑,你不能獲得對異常對象的訪問,而該對象含有重要的出錯信息。一般化異常處理代碼象這樣:

try
{
...
}
catch(System.Exception e)
{
...
}

    注意,你不能用ref或out 修飾符傳遞 e 對象給一個方法,也不能賦給它一個不同的值。

7.2.2  使用 try 和 finally 清除異常
    如果你更關心清除而不是錯誤處理, try 和 finally 會獲得你的喜歡。它不僅抑制了出錯消息,而且所有包含在
finally 塊中的代碼在異常被引發後仍然會被執行。
    盡管程序不正常終止,但你還可以為用戶獲取一條消息,如清單 7.4 所示。

    清單 7.4  在finally 語句中處理異常

1: using System;
2:
3: class Factorial
4: {
5:  public static void Main(string[] args)
6:  {
7:   long nFactorial = 1, nCurDig=1;
8:   long nComputeTo = Int64.Parse(args[0]);
9:   bool bAllFine = false;
10:
11:   try
12:   {
13:    checked
14:    {
15:     for (;nCurDig <= nComputeTo; nCurDig++)
16:      nFactorial *= nCurDig;
17:    }
18:    bAllFine = true;
19:   }
20:   finally
21:   {
22:    if (!bAllFine)
23:     Console.WriteLine("Computing {0} caused an overflow exception", nComputeTo);
24:    else
25:     Console.WriteLine("{0}! is {1}",nComputeTo, nFactorial);
26:   }
27:  }
28: }

    通過檢測該代碼,你可能會猜到,即使沒
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved