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 例外狀況
請參閱
工作
概念
參考
The try, catch, and throw Statements