許多開發者誤以為 ReadOnlyDictionary<TKey, TValue> 會複製內部字典內容,實現真正的不可變。事實上:
Dictionary 參考,仍可修改內容。ReadOnlyDictionary 中。目標:讓類別**內部**可讀寫建構資料,**外部消費者**僅能讀取,無法新增/刪除/取代項目。
類似 ReadOnlyCollection<T>,核心價值在於**封裝邊界**的保護,而非資料的深度凍結。
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>();
}
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;
}
| 優勢 | 說明 | |
|---|---|---|
| 記憶體效率 | 零額外配置,大型字典零負擔 | |
| 即時一致性 | 內部異動 (如動態載入、熱更新) 即時可見,無需同步 |
| 特性 | ReadOnlyDictionary | ImmutableDictionary |
|---|---|---|
| 命名空間 | System.Collections.ObjectModel | System.Collections.Immutable |
| 實作方式 | 包裝現有 IDictionary | 持久化資料結構 (構建新實例) |
| 修改行為 | 透過內部字典修改 (若持有參考) | 任何修改回傳新實例,原實例不變 |
| 效能 (讀取) | O(1) 直接委派 | O(log n) 樹狀結構 |
| 適用場景 | 封裝邊界保護、內部可變 | 真正不可變、函數式風格、多執行緒共享 |
ImmutableDictionary 或建構後切斷內部參考。ReadOnlyDictionary 不是魔法凍結器,而是**介面設計的護欄**。善用它能讓 API 更安全、意圖更清晰,是 .NET 類別庫設計的必備工具之一。