CodeGym /課程 /C# SELF /字典合約: IDictionary<TKey, ...

字典合約: IDictionary<TKey, TValue>

C# SELF
等級 28 , 課堂 4
開放

1. 前言

想像一下:你去一間研究貓咪的秘密實驗室上班。老闆給你一個任務——做一個電子貓咪字典,讓大家可以用名字快速查到貓的年齡、顏色還有尾巴長度。現成的解法就是 Dictionary<string, Cat>。但問題來了:後來老闆說,有些稀有品種要能記住加入順序,有時還要用特殊邏輯刪除。

那如果你要寫一個方法,能吃進任何「貓咪字典」怎麼辦?不管是什麼 class,只要支援基本的「鍵-值」操作就行。這時 IDictionary<TKey, TValue> 就派上用場啦。

IDictionary<TKey, TValue> 是 .NET 裡定義「什麼叫字典」的通用合約。它不是 class,是介面,也就是說任何真正的字典都要遵守這些規則:

  • 用 key 快速查找
  • 新增、刪除「鍵-值」對
  • 能遍歷所有對
  • 檢查 key 有沒有存在

如果 Java 在中世紀就有,騎士們打龍不是揮劍,而是揮 key 跟 value。C# 工程師只要實作 IDictionary<TKey, TValue>,龍(也就是你的 code)就被打趴啦。

2. IDictionary 介面表格

來看看這個介面主要「承諾」了哪些成員:

介面成員 型別 說明
this[TKey key]
屬性 索引子。 讓你用指定 key 取得或設定 value。讀取時:key 不存在會丟 KeyNotFoundException。寫入時:key 不存在就新增,有的話就更新。重點:這是最常用的字典操作方式。
ICollection<TKey> Keys
屬性 回傳所有 key 的集合。可以只遍歷 key。
ICollection<TValue> Values
屬性 回傳所有 value 的集合。可以只遍歷 value。
Add(TKey key, TValue value)
方法 把指定 key 跟 value 加進字典。key 已存在會丟 ArgumentException
ContainsKey(TKey key)
方法 判斷字典有沒有這個 key。有的話回傳 true,沒有就 false。這超好用,能避免用索引子查不存在的 key 時爆炸。
Remove(TKey key)
方法 把指定 key 的元素從字典移除。找到並成功刪除回傳 true,沒找到就 false(例如 key 不存在)。
TryGetValue(TKey key, out TValue value)
方法 取得指定 key 的 value。這是安全的查詢方式,如果你不確定 key 有沒有。找到就回傳 truevalue 會有對應值;沒找到就 falsevalue 會是 TValue 的預設值。這方法不會丟例外,所以在實務上超常用。

3. IDictionary<TKey, TValue> 主要成員

重點來啦!來看看 IDictionary<TKey, TValue> 裡面有啥,還有怎麼在你的 code 裡用這個「合約」。


public interface IDictionary<TKey, TValue> : ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>
{
    TValue this[TKey key] { get; set; } // 用 key 存取的索引子
    ICollection<TKey> Keys { get; }
    ICollection<TValue> Values { get; }
    void Add(TKey key, TValue value); // 新增一對(key 不能重複) 
    bool ContainsKey(TKey key); // 有這個 key 嗎?
    bool Remove(TKey key); // 用 key 刪除
    bool TryGetValue(TKey key, out TValue value); // 安全取得 value
}

來重點整理一下:

索引子 [key]

讓你用 key 取得或設定 value:

dictionary["Барсик"] = new Cat("Барсик", 2);

屬性 KeysValues

可以拿到所有 key 或所有 value 的集合。

foreach (var name in dictionary.Keys)
{
    Console.WriteLine(name);
}

方法 AddRemoveContainsKeyTryGetValue

  • Add(key, value) — 新增一對
  • Remove(key) — 用 key 刪除
  • ContainsKey(key) — 檢查有沒有這個 key
  • TryGetValue(key, out value) — 安全查 value(key 不存在也不會丟例外)

4. IDictionary<TKey, TValue> 的實戰用法

通用方法

假設你要寫一個 function,要能吃任何字典,不管裡面是 DictionarySortedDictionary,還是有人自己寫的「加密字典」。

你就把參數型別寫成 IDictionary<TKey, TValue>


static void PrintDictionary<TKey, TValue>(IDictionary<TKey, TValue> someDictionary)
{
    foreach (var pair in someDictionary)
    {
        Console.WriteLine($"{pair.Key}: {pair.Value}");
    }
}

這樣你的方法就能吃任何字典!底下是啥都行——就算有人寫了會加密 value 的字典,只要你開心。

IDictionary 傳參數

假設你做一個貓咪管理 app,想讓你的方法能吃所有設定字典,不只一種 class。像這樣:


void SetCatParameters(IDictionary<string, string> parameters)
{
    if (parameters.ContainsKey("color"))
    {
        Console.WriteLine($"把貓咪染成:{parameters["color"]}");
    }
}

同一個簽名,多種實作

來看個表格:

集合 class 有實作 IDictionary<TKey,TValue> 特色
Dictionary<TKey, TValue>
✅ 有 查找快,key 順序隨機
SortedDictionary<TKey,TValue>
✅ 有 key 會自動排序
SortedList<TKey, TValue>
✅ 有 key 會排序,比較省記憶體
(你自己實作的 class) ✅ 有 你想怎麼玩都行,但要遵守合約

5. 跟其他集合介面的關係

給資深宅宅:IDictionary<TKey, TValue> 是繼承自 ICollection<KeyValuePair<TKey, TValue>>IEnumerable<KeyValuePair<TKey, TValue>>。所以任何字典都可以:

  • foreach 遍歷所有鍵值對,
  • 用集合方法加減對,
  • 查元素數量。

foreach (var entry in myDictionary)
{
    Console.WriteLine($"{entry.Key} => {entry.Value}");
}

6. 注意事項跟常見錯誤

用索引子存取

新手最常踩的雷:用不存在的 key 查元素會丟 KeyNotFoundException


var value = myDictionary["НемаТакогоКлюча"]; // Boom!

所以最好都用 TryGetValue


if (myDictionary.TryGetValue("Мурзик", out var cat))
{
    Console.WriteLine($"找到貓咪:{cat}");
}
else
{
    Console.WriteLine($"沒找到貓咪!");
}

加已經存在的 key

如果你對已存在的 key 用 Add,會丟 ArgumentException。如果你想「加或更新」,就用索引子:


// 沒有就加,有的話就更新
myDictionary["Мурка"] = new Cat("Мурка", 5);

遍歷時修改

不要在 foreach 迴圈裡直接改字典(像是刪元素):會爆炸。如果要刪,先把要刪的 key 收集起來,再另外一個迴圈刪:


// 安全刪除元素的方法
var keysToRemove = new List<string>();
foreach (var pair in myDictionary)
{
    if (pair.Value.Age > 10) // 刪除條件
    {
        keysToRemove.Add(pair.Key);
    }
}

foreach (var key in keysToRemove)
{
    myDictionary.Remove(key);
}
2
任務
C# SELF, 等級 28, 課堂 4
上鎖
檢查字典中是否存在鍵值
檢查字典中是否存在鍵值
1
問卷/小測驗
集合合約,等級 28,課堂 4
未開放
集合合約
集合的基本介面
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION