如何使用 finally 執行清除程式碼

finally 陳述式的目的是為了確保在必要時會立即清除物件 (通常是含有外部資源的物件),即使擲回例外狀況也一樣。 這類清除的一個例子,是在使用後立即呼叫 FileStreamClose,而不等候 Common Language Runtime 回收物件的記憶體,如下所示:

static void CodeWithoutCleanup()
{
    FileStream? file = null;
    FileInfo fileInfo = new FileInfo("./file.txt");

    file = fileInfo.OpenWrite();
    file.WriteByte(0xF);

    file.Close();
}

範例

為了將上述程式碼變成 try-catch-finally 陳述式,清除程式碼會與工作程式碼分開,如下所示。

static void CodeWithCleanup()
{
    FileStream? file = null;
    FileInfo? fileInfo = null;

    try
    {
        fileInfo = new FileInfo("./file.txt");

        file = fileInfo.OpenWrite();
        file.WriteByte(0xF);
    }
    catch (UnauthorizedAccessException e)
    {
        Console.WriteLine(e.Message);
    }
    finally
    {
        file?.Close();
    }
}

因為在 OpenWrite() 呼叫之前,try 區塊內隨時都可能會發生例外狀況,或是 OpenWrite() 呼叫本身可能會失敗,所以在嘗試關閉檔案時不保證檔案處於開啟狀態。 finally 區塊新增檢查,請先確定 FileStream 物件不是null,再呼叫 Close 方法。 如果沒有 null 檢查,finally 區塊可能會擲回本身的 NullReferenceException,但應盡可能避免在 finally 區塊中擲回例外狀況。

finally 區塊中關閉資料庫連接是另一個不錯的選擇。 因為允許連接至資料庫伺服器的連接數目有時候是有限的,所以您應該盡快關閉資料庫連接。 如果在您可以關閉連接之前就擲回例外狀況,則使用 finally 區塊會比等候記憶體回收更適合。

另請參閱