使用 try/catch 處理異常
try-catch 塊的用途是捕捉和處理工作代碼所生成的異常。 有些異常可以在 catch 塊中處理,解決問題後不會再次引發異常;但更多情況下,您唯一能做的是確保引發適當的異常。
示例
在此示例中,IndexOutOfRangeException 不是最適當的異常:對本方法而言 ArgumentOutOfRangeException 更恰當些,因為錯誤是由調用方傳入的 index 參數導致的。
class
TestTryCatch
{
static
int
GetInt(
int
[] array,
int
index)
{
try
{
return
array[index];
}
catch
(System.IndexOutOfRangeException e)
// CS0168
{
System.Console.WriteLine(e.Message);
// Set IndexOutOfRangeException to the new exception's InnerException.
throw
new
System.ArgumentOutOfRangeException(
"index parameter is out of range."
, e);
}
}
}
注釋
導致異常的代碼被括在 try 塊中。 在其後面緊接著添加一個 catch 語句,以便在 IndexOutOfRangeException 發生時對其進行處理。 catch 塊處理 IndexOutOfRangeException,並引發更適當的 ArgumentOutOfRangeException 異常。 為給調用方提供盡可能多的信息,應考慮將原始異常指定為新異常的 InnerException。 因為 InnerException 屬性是只讀,所以必須在新異常的構造函數中為其賦值。
使用 finally 執行清理代碼
finally 語句的目的是確保即使在引發異常的情況下也能立即進行必要的對象(通常是保存外部資源的對象)清理。此類清理功能的一個示例是在使用後立即對 FileStream 調用 Close,而不是等待公共語言運行時對該對象進行垃圾回收,如下所示:
static
void
CodeWithoutCleanup()
{
System.IO.FileStream file =
null
;
System.IO.FileInfo fileInfo =
new
System.IO.FileInfo(
"C:\\file.txt"
);
file = fileInfo.OpenWrite();
file.WriteByte(0xF);
file.Close();
}
為了將上面的代碼轉換為 try-catch-finally 語句,需要將清理代碼與工作代碼分開,如下所示。
? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24static
void
CodeWithCleanup()
{
System.IO.FileStream file =
null
;
System.IO.FileInfo fileInfo =
null
;
try
{
fileInfo =
new
System.IO.FileInfo(
"C:\\file.txt"
);
file = fileInfo.OpenWrite();
file.WriteByte(0xF);
}
catch
(System.UnauthorizedAccessException e)
{
System.Console.WriteLine(e.Message);
}
finally
{
if
(file !=
null
)
{
file.Close();
}
}
}
因為在 OpenWrite() 調用前,try 塊內隨時都有可能發生異常,OpenWrite() 調用本身也有可能失敗,所以我們無法保證該文件在我們嘗試關閉它時處於打開狀態。 finally 塊添加了一項檢查,以確保在調用 Close 方法前,FileStream 對象不為 null。如果沒有 null 檢查,finally 塊可能引發自身的 NullReferenceException,但是應當盡可能避免在 finally 塊中引發異常。
在 finally 塊中關閉數據庫連接是另一個不錯的選擇。因為有時候數據庫服務器允許的連接數是有限的,所以應盡快關閉數據庫連接。在由於引發了異常而無法關閉連接的情況下,使用 finally 塊也是比等待垃圾回收更好的一種選擇。