Share via


try-catch (C# 參考)

更新:2007 年 11 月

try-catch 陳述式是由其後跟隨一個或多個 catch 子句的 try 區塊組成,以指定不同例外狀況的處理常式。擲回例外狀況時,Common Language Runtime (CLR) 會尋找處理此例外狀況的 catch 陳述式。如果目前執行的方法未包含這種 catch 區塊,CLR 會檢查呼叫目前方法的方法,一直向上檢查至呼叫堆疊。如果找不到 catch 區塊,CLR 就會顯示未處理的例外狀況訊息以告知使用者,並停止執行程式。

try 區塊中含有可能會導致例外狀況並受到嚴密監控的程式碼。執行區塊直到擲回例外狀況或已成功完成。例如,以下轉換 null 物件的嘗試會引發 NullReferenceException 例外狀況:

object o2 = null;
try
{
    int i2 = (int)o2;   // Error
}

雖然 catch 子句可在無引數的情況下使用來呼叫任何類型的例外狀況,但不建議這種用法。一般來說,您應該只攔截那些您知道如何復原的例外狀況。因此,您一定要指定衍生自 System.Exception 的物件引數,例如:

catch (InvalidCastException e) 
{
}

在相同的 try-catch 陳述式中,有可能使用一個以上特定 catch 子句。此時由於 catch 子句是依照順序進行檢查,因此 catch 子句的順序就非常重要。在較不特定的例外狀況之前攔截較特定的例外狀況。如果因 catch 區塊順序而導致永遠無法執行到後面的區塊,編譯器會產生錯誤。

您可以在 catch 區塊中使用 throw 陳述式,再度擲回已經被 catch 陳述式攔截的例外狀況。例如:

catch (InvalidCastException e) 
{
    throw (e);    // Rethrowing exception e
}

您也可以擲回新的例外狀況。執行這項作業時,要將攔截的例外狀況指定為內部例外狀況:

catch (InvalidCastException e) 
{
   // Can do cleanup work here.
    throw new CustomException("Error message here.", e);
}

如果要重新擲回目前由沒有參數 catch 子句處理的例外狀況,請使用不含引數的 throw 陳述式。例如:

catch
{
    throw;
}

在 try 區塊內只可以對在其中宣告的變數進行初始化,否則該區塊執行完畢之前可能會產生例外狀況。例如下列程式碼範例中的 x 變數就是在 try 區塊中進行初始化。Write(x) 陳述式中,如果嘗試在 try 區塊外面使用這個變數,會產生以下編譯器錯誤:使用未指派的區域變數

static void Main() 
{
    int x;
    try 
    {
        // Don't initialize this variable here.
        x = 123;
    }
    catch
    {
    }
    // Error: Use of unassigned local variable 'x'.
    Console.Write(x);
}

如需 catch 的詳細資訊,請參閱 try-catch-finally

範例

在這個範例中,try 區塊包含 ProcessString 方法的呼叫,此呼叫可能會造成例外狀況。catch 子句包含只會在畫面上顯示訊息的例外狀況處理常式 (Exception Handler)。從 MyMethod 內部呼叫 throw 陳述式時,系統會尋找 catch 陳述式並且顯示 Exception caught 訊息。

    class TryFinallyTest
{
    static void ProcessString(string s)
    {
        if (s == null)
        {
            throw new ArgumentNullException();
        }
    }

    static void Main()
    {
        string s = null; // For demonstration purposes.

        try
        {            
            ProcessString(s);
        }

        catch (Exception e)
        {
            Console.WriteLine("{0} Exception caught.", e);
        }
    }
}
    /*
    Output:
    System.ArgumentNullException: Value cannot be null.
       at TryFinallyTest.Main() Exception caught.
     * */

在這個範例中,使用兩個 catch 陳述式。會攔截最特定的例外狀況 (會先出現)。

class ThrowTest3
{
    static void ProcessString(string s)
    {
        if (s == null)
        {
            throw new ArgumentNullException();
        }
    }

    static void Main()
    {
        try
        {
            string s = null;
            ProcessString(s);
        }
        // Most specific:
        catch (ArgumentNullException e)
        {
            Console.WriteLine("{0} First exception caught.", e);
        }
        // Least specific:
        catch (Exception e)
        {
            Console.WriteLine("{0} Second exception caught.", e);
        }
    }
}
/*
 Output:
System.ArgumentNullException: Value cannot be null.
   at TryFinallyTest.Main() First exception caught.
*/

在上述範例中,如果您以最不特定的 catch 子句開始,就會收到錯誤訊息:

A previous catch clause already catches all exceptions of this or a super type ('System.Exception')

但是為了攔截最不特定的例外狀況,將 throw 陳述式用下列來取代:

throw new Exception();

C# 語言規格

如需詳細資料,請參閱 C# 語言規格中的下列章節:

  • 5.3.3.13 Try-catch 陳述式

  • 8.10 try 陳述式

  • 16 例外狀況

請參閱

工作

HOW TO:明確擲回例外狀況

概念

C# 程式設計手冊

參考

C# 關鍵字

The try, catch, and throw Statements

例外處理陳述式 (C# 參考)

throw (C# 參考)

try-finally (C# 參考)

其他資源

C# 參考