C# 程式設計人員會使用 try 區塊來分割可能受到例外狀況影響的程式代碼。 相關聯的 catch 區塊可用來處理任何產生的例外狀況。
finally 區塊包含程式碼,不論是否在 try 區塊中擲回例外狀況,例如釋放在 try 區塊中配置的資源。
try區塊需要一或多個相關聯的catch區塊,或finally區塊,或兩者。
下列範例顯示 try-catch 語句、 try-finally 語句和 try-catch-finally 語句。
try
{
// Code to try goes here.
}
catch (SomeSpecificException ex)
{
// Code to handle the exception goes here.
// Only catch exceptions that you know how to handle.
// Never catch base class System.Exception without
// rethrowing it at the end of the catch block.
}
try
{
// Code to try goes here.
}
finally
{
// Code to execute after the try block goes here.
}
try
{
// Code to try goes here.
}
catch (SomeSpecificException ex)
{
// Code to handle the exception goes here.
}
finally
{
// Code to execute after the try (and possibly catch) blocks
// goes here.
}
缺少try區塊或catch區塊的finally區塊會導致編譯器錯誤。
「Catch」區塊
catch區塊可以指定要攔截的例外狀況類型。 類型規格稱為 例外狀況篩選條件。 例外狀況類型應該衍生自 Exception。 一般而言,除非您知道如何處理區塊中Exception可能擲回的所有例外狀況,或已在區塊結尾try包含 throw 語句,否則請勿指定catch為例外狀況篩選條件。
具有不同例外狀況類別的多個 catch 區塊可以鏈結在一起。 區塊 catch 會從程序代碼的上到下進行評估,但針對擲回的每個例外狀況,只會執行一個 catch 區塊。 會執行第一 catch 個區塊,指定所擲回例外狀況的確切類型或基類。 如果語句中存在沒有任何類型的區塊,且catch區塊未指定任何相符的例外類別,則會選擇catch區塊。 請務必先放置 catch 具有最特定(也就是最衍生的)例外狀況類別的區塊。
當下列條件成立時,攔截例外狀況:
- 您已充分瞭解為何可能引發例外狀況,而且您可以實作特定復原措施,例如當您攔截 FileNotFoundException 物件時,提示使用者輸入新檔名。
- 您可以建立並擲回新的更特定的例外。
int GetInt(int[] array, int index) { try { return array[index]; } catch (IndexOutOfRangeException e) { throw new ArgumentOutOfRangeException( "Parameter index is out of range.", e); } } - 您想在進一步處理之前,先部分處理例外狀況。 在下列範例中,
catch區塊可用來在重新擲回例外狀況之前,新增一個條目至錯誤記錄檔。try { // Try to access a resource. } catch (UnauthorizedAccessException e) { // Call a custom error logging procedure. LogError(e); // Re-throw the error. throw; }
您也可以指定 例外狀況篩選 條件,將布爾表達式新增至 catch 子句。 例外狀況篩選條件指出特定 catch 子句只有在該條件為 true 時才相符。 在下列範例中,這兩個 catch 子句都會使用相同的例外狀況類別,但會檢查額外的條件來建立不同的錯誤訊息:
int GetInt(int[] array, int index)
{
try
{
return array[index];
}
catch (IndexOutOfRangeException e) when (index < 0)
{
throw new ArgumentOutOfRangeException(
"Parameter index cannot be negative.", e);
}
catch (IndexOutOfRangeException e)
{
throw new ArgumentOutOfRangeException(
"Parameter index cannot be greater than the array size.", e);
}
}
一律傳 false 回的例外狀況篩選條件可用來檢查所有例外狀況,但無法處理這些例外狀況。 一般用途是記錄例外狀況:
public class ExceptionFilter
{
public static void Main()
{
try
{
string? s = null;
Console.WriteLine(s.Length);
}
catch (Exception e) when (LogException(e))
{
}
Console.WriteLine("Exception must have been handled");
}
private static bool LogException(Exception e)
{
Console.WriteLine($"\tIn the log routine. Caught {e.GetType()}");
Console.WriteLine($"\tMessage: {e.Message}");
return false;
}
}
LogException 方法總是傳回 false,沒有任何使用此例外篩選器的 catch 子句匹配。 catch 子句可以是一般的,使用 System.Exception,後續的子句可以處理更特定的例外狀況類別。
最終區塊
區塊 finally 可讓您清除區塊中 try 執行的動作。 如果 finally 區塊存在,它會在 try 區塊及任何相符的 catch 區塊之後執行,最後執行。 區塊 finally 總是會執行,無論是擲回例外狀況還是找到符合例外狀況類型的區塊 catch。
區塊 finally 可用來釋放資源,例如檔案流、資料庫連接和圖形句柄,而不需等待執行時期的垃圾收集器完成對物件的完成作業。
在下列範例中,finally 區塊是用來關閉在 try 區塊中開啟的檔案。 請注意,在關閉檔案之前,會先檢查檔句柄的狀態。
try如果區塊無法開啟檔案,檔案句柄仍保持null的值,而finally區塊不會嘗試關閉它。 相反地,如果檔案在 區塊中 try 成功開啟,區塊 finally 就會關閉開啟的檔案。
FileStream? file = null;
FileInfo fileinfo = new System.IO.FileInfo("./file.txt");
try
{
file = fileinfo.OpenWrite();
file.WriteByte(0xF);
}
finally
{
// Check for null because OpenWrite might have failed.
file?.Close();
}
C# 語言規格
如需詳細資訊,請參閱 C# 語言規格中的例外狀況和 try 語句。 語言規格是 C# 語法和使用方式的最終來源。