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# 語法和使用方式的最終來源。