try-catch (C# 參考)

更新:2010 年 7 月

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 區塊順序而導致永遠無法執行到後面的區塊,編譯器會產生錯誤。

throw 陳述式可以用於 catch 區塊中,以重新擲回 catch 陳述式所攔截的例外狀況。 下列範例會從 IOException 例外狀況中擷取來源資訊,然後將例外狀況擲回到父方法。

catch (FileNotFoundException e)
{
    // FileNotFoundExceptions are handled here.
}
catch (IOException e)
{
    // Extract some information from this exception, and then 
    // throw it to the parent method.
    if (e.Source != null)
        Console.WriteLine("IOException source: {0}", e.Source);
    throw;
}

您可以攔截一個例外狀況,並擲回不同的例外狀況。 當您這樣做時,請指定您當做內部例外狀況攔截到的例外狀況,如下列範例中所示。

catch (InvalidCastException e) 
{
    // Perform some action here, and then throw a new exception.
    throw new YourCustomException("Put your error message here.", e);
}

當指定的條件為 true 時,您也可以重新擲回例外狀況,如下列範例中所示。

catch (InvalidCastException e)
{
    if (e.Data == null)
    {
        throw;
    }
    else
    {
        // Take some action.
    }
 }

從 try 區塊內部,指初始化在此宣告的變數。 否則,區塊執行完成前可能會發生例外狀況。 例如下列程式碼範例中的 n 變數就是在 try 區塊中進行初始化。 Write(n) 陳述式中,如果嘗試在 try 區塊外面使用這個變數,會產生以下編譯器錯誤。

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

如需 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 Test.ThrowTest3.ProcessString(String s) ... 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# 語言規格。 語言規格是 C# 語法和用法的決定性來源。

請參閱

工作

HOW TO:明確擲回例外狀況

參考

C# 關鍵字

try, catch, and throw Statements (C++)

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

throw (C# 參考)

try-finally (C# 參考)

概念

C# 程式設計手冊

其他資源

C# 參考

變更記錄

日期

記錄

原因

2010 年 7 月

已更新 throw 範例。

客戶回函。