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

ReadOnlyDictionary 應用場景深度解析:封裝內部可寫、對外唯讀的最佳實踐

     編輯:關於.NET

常見誤區:以為它能「深度凍結」字典

許多開發者誤以為 ReadOnlyDictionary<TKey, TValue> 會複製內部字典內容,實現真正的不可變。事實上:

  • 它**只是包裝器**,不複製資料。
  • 若外部持有原始 Dictionary 參考,仍可修改內容。
  • 修改會即時反映在 ReadOnlyDictionary 中。

真正設計意圖:介面層級的「唯讀契約」

目標:讓類別**內部**可讀寫建構資料,**外部消費者**僅能讀取,無法新增/刪除/取代項目。

類似 ReadOnlyCollection<T>,核心價值在於**封裝邊界**的保護,而非資料的深度凍結。

實戰場景:FileStructure 檔案結構模型

❌ 錯誤示範:暴露可寫 Dictionary

public class FileStructure
{
    public Dictionary<string, Field> Fields { get { return _fields; } }
    // 呼叫端可任意:fields.Add("Hack", ...)、fields.Clear()、fields["DosHeader"] = null
    private Dictionary<string, Field> _fields = new Dictionary<string, Field>();
}

✅ 正確做法:暴露 ReadOnlyDictionary

public class FileStructure
{
    // 對外唯讀介面
    public ReadOnlyDictionary<string, Field> Fields { get { return _roFields; } }

    public FileStructure()
    {
        _fields = new Dictionary<string, Field>();
        _roFields = new ReadOnlyDictionary<string, Field>(_fields); // 包裝

        // 內部建構階段:正常寫入
        _fields.Add("DosHeader", new Field(...));
        _fields.Add("PEHeader", new Field(...));
        _fields.Add("OptionalHeader", new Field(...));
    }

    // 內部方法仍可修改
    public void AddField(string name, Field field)
    {
        _fields[name] = field; // 修改即時反映在 Fields 唯讀視圖中
    }

    private Dictionary<string, Field> _fields;
    private ReadOnlyDictionary<string, Field> _roFields;
}

為什麼不複製資料?兩大優勢

進階用法:建構完成後「凍結」內部字典

若需**建構後完全不可變**,可在建構函式結尾將 `_fields` 設為 null 或替換為 ImmutableDictionary (需 NuGet System.Collections.Immutable):

public FileStructure()
{
    var temp = new Dictionary<string, Field>();
    temp.Add("DosHeader", new Field(...));
    // ... 建構邏輯

    _roFields = new ReadOnlyDictionary<string, Field>(temp);
    _fields = null; // 斷開內部寫入路徑,編譯期防呆
}

對比:ReadOnlyDictionary vs ImmutableDictionary

優勢說明
記憶體效率零額外配置,大型字典零負擔
即時一致性內部異動 (如動態載入、熱更新) 即時可見,無需同步
特性ReadOnlyDictionaryImmutableDictionary
命名空間System.Collections.ObjectModelSystem.Collections.Immutable
實作方式包裝現有 IDictionary持久化資料結構 (構建新實例)
修改行為透過內部字典修改 (若持有參考)任何修改回傳新實例,原實例不變
效能 (讀取)O(1) 直接委派O(log n) 樹狀結構
適用場景封裝邊界保護、內部可變真正不可變、函數式風格、多執行緒共享

最佳實踐總結

  1. 公開屬性回傳 ReadOnlyDictionary,建構子內部用私有 Dictionary 建構。
  2. 不要**為了「唯讀」而複製字典**,除非有明確不可變需求。
  3. 文件化契約:XML 註解標註「此集合為唯讀視圖,內部可能異動」。
  4. 需要真不可變? 改用 ImmutableDictionary 或建構後切斷內部參考。

結語

ReadOnlyDictionary 不是魔法凍結器,而是**介面設計的護欄**。善用它能讓 API 更安全、意圖更清晰,是 .NET 類別庫設計的必備工具之一。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved