首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

Effective C# 原則 18:實作標準 Dispose 模式(三)

     編輯:關於C語言

衍生類別的資源清理

若衍生類別有額外清理工作,讓它實作 Dispose 方法:

public class DerivedResourceHog : MyResourceHog
{
    private bool _disposed = false;
    protected override void Dispose(bool isDisposing)
    {
        if (_disposed) return;
        if (isDisposing) { /* free managed resources */ }
        /* free unmanaged resources */
        base.Dispose(isDisposing);
        _disposed = true;
    }
}

注意,衍生與基類各有處理狀態旗標,完全被動。重設旗標掩蓋處理時可能發生的錯誤,且為單一型別處理,而非處理構成物件的所有型別。(譯註:基類與子類各自標記,互不影響。)

被動撰寫清理方法的重要性

物件可能以任何順序被處理,你可能遇到:成員在呼叫 Dispose 前已被處理。Dispose() 可多次呼叫,重複呼叫無事發生。解構函式同樣規則。物件參考存在記憶體時無需檢查 null,但參考的物件可能已處理或解構。

嚴正警告:清理方法只能釋放資源

對任何與處理和資源清理相關的方法,必須只釋放資源!切勿在處理過程中添加其他任務。否則會在物件生命週期遇到嚴重複雜問題。物件建立時出生,GC 辨識時死亡。程式無法存取時視為睡眠。解構函式在死亡前有最後一口氣,只應清理非受控資源。若解構函式讓物件重新可存取,物件「復活」——這並不好。

復活物件的危害範例

public class BadClass
{
    private readonly ArrayList _finalizedList;
    private string _msg;
    public BadClass(ArrayList badList, string msg) { _finalizedList = badList; _msg = (string)msg.Clone(); }
    ~BadClass() { _finalizedList.Add(this); } // 物件重新可達,復活!
}

復活物件會導致:GC 相信不再需呼叫解構函式;資源可能已失效;GC 不移除僅被解構佇列參考的物件,但它們可能已解構無法使用。C# 無法控制解構順序,此結構不可靠,切勿嘗試。

實務建議

  • 托管環境中,非每個類別都需解構函式;僅需釋放非受控資源或包含實作 IDisposable 成員時添加。
  • 甚至只需實作 IDisposable,無需解構函式,否則限制衍生類別實作標準 Dispose 模式。
  • 遵守標準 Dispose 模式,讓你、使用者、衍生類別作者生活輕鬆。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved