Dictionary<TKey, TValue> 是 C# 中最常用的泛型集合之一,提供鍵值對(Key-Value Pair)的快速查找、新增、刪除與列舉功能。底層採用雜湊表實現,查找與插入的平均時間複雜度為 O(1)。本文透過一個完整的 Console 應用程式範例,詳細示範 Dictionary 的核心操作,包含新增、查詢、修改、移除、例外處理、TryGetValue、ContainsKey、列舉 Keys/Values、KeyValuePair 等實用技巧。
using System;
using System.Collections.Generic;
namespace DictionaryDemo
{
class Program
{
static void Main(string[] args)
{
// 1. 建立 Dictionary
var openWith = new Dictionary();
// 2. 新增元素(鍵不可重複,值可重複)
openWith.Add("txt", "notepad.exe");
openWith.Add("bmp", "paint.exe");
openWith.Add("dib", "paint.exe"); // 值重複沒問題
openWith.Add("rtf", "wordpad.exe");
Console.WriteLine("=== 初始集合 ===");
PrintDictionary(openWith);
// 3. 嘗試新增重複鍵 → 會拋出 ArgumentException
try
{
openWith.Add("txt", "winword.exe");
}
catch (ArgumentException ex)
{
Console.WriteLine($"\n[例外處理] {ex.Message}");
// 輸出:An element with Key = "txt" already exists.
}
// 4. 使用索引子 讀取/修改 值
Console.WriteLine($"\n[索引子讀取] rtf 對應值:{openWith["rtf"]}");
openWith["rtf"] = "winword.exe"; // 修改現有鍵的值
Console.WriteLine($"[索引子修改] rtf 新值:{openWith["rtf"]}");
// 5. 索引子新增不存在的鍵
openWith["doc"] = "winword.exe"; // 相當於 Add
Console.WriteLine($"[索引子新增] doc:{openWith["doc"]}");
// 6. 讀取不存在的鍵 → 拋出 KeyNotFoundException
try
{
Console.WriteLine(openWith["tif"]);
}
catch (KeyNotFoundException ex)
{
Console.WriteLine($"\n[例外處理] {ex.Message}");
}
// 7. 推薦:使用 TryGetValue 避免例外(效能更好)
string value = "";
if (openWith.TryGetValue("tif", out value))
Console.WriteLine($"[TryGetValue] tif = {value}");
else
Console.WriteLine("[TryGetValue] 找不到鍵 'tif'");
// 8. ContainsKey:新增前先檢查
if (!openWith.ContainsKey("ht"))
{
openWith.Add("ht", "hypertrm.exe");
Console.WriteLine($"\n[ContainsKey] 新增 ht:{openWith["ht"]}");
}
// 9. 列舉所有 KeyValuePair
Console.WriteLine("\n=== 列舉 KeyValuePair ===");
foreach (var kvp in openWith)
{
Console.WriteLine($"Key = {kvp.Key}, Value = {kvp.Value}");
}
// 10. 只列舉 Values
Console.WriteLine("\n=== 列舉 Values ===");
foreach (string s in openWith.Values)
Console.WriteLine($"Value = {s}");
// 11. 只列舉 Keys
Console.WriteLine("\n=== 列舉 Keys ===");
foreach (string s in openWith.Keys)
Console.WriteLine($"Key = {s}");
// 12. 移除鍵值對
Console.WriteLine("\n=== 移除 doc ===");
openWith.Remove("doc");
if (!openWith.ContainsKey("doc"))
Console.WriteLine("Key \"doc\" 已成功移除。");
Console.WriteLine("\n=== 最終集合 ===");
PrintDictionary(openWith);
Console.ReadKey();
}
static void PrintDictionary(Dictionary dict)
{
foreach (var kvp in dict)
Console.WriteLine($" {kvp.Key} → {kvp.Value}");
}
}
}
| 方法/屬性 | 用途 | 備註 |
|---|---|---|
Add(key, value) | 新增鍵值對 | 鍵重複拋出 ArgumentException |
Remove(key) | 移除指定鍵 | 回傳 bool,表示是否成功移除 |
TryGetValue(key, out value) | 嘗試取得值 | 推薦,避免例外,效能最佳 |
ContainsKey(key) | 檢查鍵是否存在 | O(1),新增前建議先檢查 |
ContainsValue(value) | 檢查值是否存在 | O(n),需遍歷 |
Clear() | 清空所有元素 | |
Count | 元素數量 | 屬性 |
Keys | 取得鍵集合 | 回傳 KeyCollection |
Values | 取得值集合 | 回傳 ValueCollection |
this[key] (索引子) | 讀寫值 | 讀取不存在鍵拋出例外;寫入不存在鍵等同 Add |
public class Person
{
public string Id { get; set; }
public string Name { get; set; }
public override bool Equals(object obj)
{
return obj is Person other && Id == other.Id;
}
public override int GetHashCode()
{
return Id.GetHashCode();
}
}
若未正確實作,Dictionary 將無法正確判斷鍵是否重複。
Dictionary<TKey, TValue> 非線程安全。多線程環境下請使用 ConcurrentDictionary<TKey, TValue>(位於 System.Collections.Concurrent),提供無鎖或細粒度鎖的執行緒安全操作。
var dict = new Dictionary
{
["apple"] = 1,
["banana"] = 2,
["orange"] = 3
};
在 foreach 迴圈中呼叫 Add 或 Remove 會拋出 InvalidOperationException。需先蒐集要修改的鍵,迴圈結束後再操作。
Dictionary<TKey, TValue> 是高效能鍵值對集合的首選。掌握 TryGetValue、ContainsKey、索引子讀寫、安全列舉等核心操作,能讓你在實務開發中游刃有餘。記住:鍵不可重複、值可重複、非線程安全、自訂 Key 需正確實作雜湊邏輯。