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

C# 泛型集合 Dictionary 完整指南:建立、查詢、遍歷、移除與效能優化

     編輯:C# 入門

前言

Dictionary<TKey, TValue> 是 .NET 最常用的雜湊表實作,提供 **O(1) 平均查詢/插入/刪除** 效能。本文系統整理從建立到進階用法的完整指南。

命名空間與基本特性

  • 命名空間:System.Collections.Generic
  • 組件:mscorlib / System.Collections.dll
  • 鍵值唯一:Key 不可重複,null 可作為 Value (參考型別),但**不可**作為 Key
  • 無序:不保證列舉順序 (若需有序用 SortedDictionary 或 SortedList)

建立與初始化


// 1. 預設容量
var dict = new Dictionary();

// 2. 指定初始容量 (避免擴容開銷)
var dict2 = new Dictionary(1000);

// 3. 指定比較器 (忽略大小寫、自定義相等性)
var dict3 = new Dictionary(StringComparer.OrdinalIgnoreCase);

// 4. 集合初始化器 (C# 6+)
var dict4 = new Dictionary
{
    ["C#"] = 1,
    ["Java"] = 2,
    ["Python"] = 3
};

// 5. 從現有字典複製
var dict5 = new Dictionary(dict4);

核心操作 API

操作方法回傳/行為例外情況
新增Add(key, value)voidKey 重複 → ArgumentException
新增/更新dict[key] = value索引器Key 不存在 → 新增;存在 → 覆蓋
嘗試新增TryAdd(key, value) (.NET Core 2.0+)bool不拋例外,失敗回傳 false
查詢dict[key]TValueKey 不存在 → KeyNotFoundException
安全查詢TryGetValue(key, out value)bool不拋例外,推薦高頻查詢使用
存在性檢查ContainsKey(key) / ContainsValue(value)boolValue 查詢為 O(n)
移除Remove(key)bool不存在回傳 false
條件移除Remove(key, out value) (.NET Core 3.0+)bool同時取得被移除值
清空Clear()void
數量CountintO(1)

遍歷方式比較


var dict = new Dictionary { ["A"] = 1, ["B"] = 2, ["C"] = 3 };

// 1. KeyValuePair 結構體 (最常用,同時取得 Key/Value)
foreach (var kvp in dict)
{
    Console.WriteLine($"Key={kvp.Key}, Value={kvp.Value}");
}

// 2. 僅遍歷 Keys
foreach (var key in dict.Keys)
{
    Console.WriteLine(key);
}

// 3. 僅遍歷 Values
foreach (var value in dict.Values)
{
    Console.WriteLine(value);
}

// 4. LINQ 查詢 (投影、過濾、排序)
var top3 = dict.OrderByDescending(kvp => kvp.Value).Take(3);
foreach (var kvp in top3) { ... }

// 5. 並行遍歷 (.NET 6+ Parallel.ForEach)
Parallel.ForEach(dict, kvp => { /* 執行緒安全需自行鎖定 */ });

進階用法

1. 複合鍵


// 選項 A: Tuple (C# 7+ ValueTuple 自動實作 Equals/GetHashCode)
var dict = new Dictionary<(int Year, int Month), double>();
dict[(2024, 1)] = 100.5;

// 選項 B: 自定義結構體 (需正確實作 Equals/GetHashCode)
struct CompositeKey { public int A; public string B; }
var dict2 = new Dictionary();

2. 取得或新增模式


// 傳統寫法
if (!dict.TryGetValue(key, out var value))
{
    value = ComputeExpensiveValue(key);
    dict[key] = value;
}

// .NET 6+ GetOrAdd (需引用 System.Collections.Generic)
var value = dict.GetOrAdd(key, k => ComputeExpensiveValue(k));

3. 字典合併


var dict1 = new Dictionary { ["A"] = 1 };
var dict2 = new Dictionary { ["B"] = 2, ["A"] = 99 };

// 選項 A: 手動合併 (後者覆蓋)
foreach (var kvp in dict2) dict1[kvp.Key] = kvp.Value;

// 選項 B: LINQ (建立新字典)
var merged = dict1.Concat(dict2)
    .GroupBy(kvp => kvp.Key)
    .ToDictionary(g => g.Key, g => g.Last().Value); // 保留後者

4. 序列化 (JSON)


var json = System.Text.Json.JsonSerializer.Serialize(dict);
// {"C#":1,"Java":2,"Python":3}

var restored = System.Text.Json.JsonSerializer.Deserialize>(json);

效能優化關鍵

場景建議理由
已知大約資料筆數建構子指定 capacity避免多次陣列擴容 (2倍增長) 與重新雜湊
高頻查詢使用 TryGetValue 而非 ContainsKey + 索引器單次雜湊查找 vs 兩次
Key 為字串考慮 StringComparer.Ordinal (預設) vs OrdinalIgnoreCaseOrdinal 最快,忽略大小寫需額外正規化
Key 為結構體確保正確實作 GetHashCode (組合所有欄位)差的雜湊函數導致碰撞,退化為 O(n)
大量刪除後記憶體釋放無內建 Trim,可 new Dictionary(oldDict) 重建內部陣列不會自動縮減
多執行緒讀寫使用 ConcurrentDictionary 或自行 ReaderWriterLockSlimDictionary 非執行緒安全

常見錯誤與陷阱


// ❌ 修改 Value 為參考型別時,直接修改物件內容不會觸發字典更新 (因為 Value 是參考)
dict["key"].SomeProperty = newValue; // 這沒問題,因為改的是物件內容

// ❌ 遍歷時修改集合
foreach (var kvp in dict) { if (kvp.Value < 0) dict.Remove(kvp.Key); } 
// → InvalidOperationException: Collection was modified

// ✅ 正確:先收集要刪除的 Key
var toRemove = dict.Where(kvp => kvp.Value < 0).Select(kvp => kvp.Key).ToList();
foreach (var key in toRemove) dict.Remove(key);

// ❌ 以可變物件作 Key 並修改其內容
var listKey = new List { 1, 2 };
dict[listKey] = "value";
listKey.Add(3); // 修改 Key 內容 → 雜湊碼改變 → 找不到原項目!

// ✅ Key 必須不可變

總結

Dictionary<TKey, TValue> 是高效查找的首選集合。掌握 TryGetValue、TryAdd、GetOrAdd 等現代 API,配合正確的**初始容量**、**比較器選擇**、**Key 不可變性**、**執行緒安全**策略,能發揮最大效能並避免常見 Bug。進階場景可考慮 ConcurrentDictionary、FrozenDictionary (.NET 8+ 唯讀高效能)、SortedDictionary 等變體。

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