C# IDictionary和Dictionary 作者:马育民 • 2025-06-29 21:38 • 阅读:10002 # 介绍 在C#编程中,`IDictionary` 和 `Dictionary` 是处理键值对集合时常用的类型。下面将详细介绍它们的概念、区别及应用场景,并提供相应的代码示例。 见下面的两张身份证图片,观察区别,哪个身份证更加易于理解 [](https://www.malaoshi.top/upload/0/0/1EF3XRBGQEZi.jpg) [](https://www.malaoshi.top/upload/0/0/1EF3WKIIcywf.jpg) “姓名”、“性别”就是key,与之对应的具体内容就是value ### 类比Java `IDictionary` 相当于 `Map` `Dictionary` 相当于 `HashMap` ### 1. IDictionary 接口 #### **概念** - **定义**:`IDictionary` 是一个泛型接口,定义了操作键值对集合的基本方法和属性。 - **特点**: - 键必须唯一,且不能为 `null`(除非 `TKey` 是引用类型)。 - 值可以重复或为 `null`。 - 提供了添加、删除、查找元素等方法。 - **应用场景**:当需要编写通用代码,支持不同字典实现时使用。 #### **常用方法和属性** | 成员 | 描述 | |--------------------|-------------------------------| | `Add(key, value)` | 添加键值对。 | | `ContainsKey(key)` | 检查是否包含指定键。 | | `Remove(key)` | 移除指定键的元素。 | | `TryGetValue(key, out value)` | 获取键对应的值(安全方式)。 | | `this[key]` | 通过索引器访问或设置值。 | | `Keys` | 获取所有键的集合。 | | `Values` | 获取所有值的集合。 | ### **2. Dictionary 类** #### **概念** - **定义**:`Dictionary` 是 `IDictionary` 的具体实现类,基于哈希表实现。 - **特点**: - 动态扩容,无需预先指定大小。 - 插入、查找和删除操作的时间复杂度接近 O(1)。 - 非线程安全(如需线程安全,可使用 `ConcurrentDictionary`)。 - **应用场景**:需要高效存储和快速查找键值对的场景。 ### **3. 核心区别** | **IDictionary** | **Dictionary** | |-------------------------------|-------------------------------| | 接口(不能直接实例化) | 具体类(可直接实例化) | | 定义契约,不提供具体实现 | 提供基于哈希表的高效实现 | | 用于抽象编程(依赖倒置原则) | 用于具体实现 | # 例子 ### 创建 要使用 `Dictionary`,同样需要引入 `System.Collections.Generic` 命名空间。在创建字典时,需要指定键和值的类型,例如,如果我们希望以字符串作为键,以整数作为值,则创建一个 `Dictionary` 类型的字典。 ``` using System.Collections.Generic; // 创建一个以字符串作为键,以整数作为值的字典 Dictionary ageDict = new Dictionary(); ``` ### 初始化 从C# 3.0 之后提供了初始化器,可以初始化Dictionary ``` Dictionary ageDict = new Dictionary { {"Alice", 25}, {"Bob", 30}, {"Charlie", 22} }; ``` ### 添加元素-方式一 可以使用 `Add()` 方法向字典中添加键值对。 **注意:**如果键已经 **存在** 于字典中,则 `Add()` 方法将会抛出异常。 ``` // 添加键值对到字典中 ageDict.Add("Alice", 25); ageDict.Add("Bob", 30); ageDict.Add("Charlie", 22); ``` ### 添加元素-方式二 如果我们希望键可以重复,则可以使用索引符号 `[]` 直接给字典赋值,这样如果键已经存在,则会更新对应的值。 ``` // 直接赋值给字典,如果键已存在,则更新对应的值 ageDict["Alice"] = 26; ``` ### 访问元素-方式一 可以通过键访问字典中的值。使用索引符号 `[键]` 来获取对应的值。 **注意:**如果字典中不存在该键,则会抛出异常。 ``` // 通过键访问字典中的值 int aliceAge = ageDict["Alice"]; // 获取"Alice"对应的值,此处为26 ``` ### 访问元素-方式二 为了避免抛出异常,可以使用 `TryGetValue()` 方法。 ``` // 使用 TryGetValue() 避免抛出异常 if (ageDict.TryGetValue("Bob", out int bobAge)) { Console.WriteLine($"Bob's age: {bobAge}"); // 输出"Bob's age: 30" } else { Console.WriteLine("Bob's age not found."); } ``` ### 删除元素 可以使用 `Remove()` 方法根据键从字典中删除元素。 ``` // 删除字典中的键值对 ageDict.Remove("Charlie"); ``` ### Clear情况元素 `Clear()` 方法用于清空整个字典,即删除所有键值对。 ### 遍历字典 可以使用 `foreach` 循环遍历字典中的所有键值对,或者分别遍历键和值。 ``` // 遍历键值对 foreach (var kvp in ageDict) { Console.WriteLine($"{kvp.Key}: {kvp.Value}"); } // 遍历键 foreach (var key in ageDict.Keys) { Console.WriteLine(key); } // 遍历值 foreach (var value in ageDict.Values) { Console.WriteLine(value); } ``` ### 常见问题 1. **键为 `null`**:若 `TKey` 为引用类型,插入 `null` 键会抛出 `ArgumentNullException`。 2. **重复键**:插入重复键会抛出 `ArgumentException`,可先使用 `ContainsKey` 检查。 3. **线程安全**:`Dictionary` 非线程安全,多线程环境下需使用 `ConcurrentDictionary`。 # 其他方法 ### Count Count属性用于获取字典中键值对的数量。 ``` int count = ageDict.Count; // 获取键值对的数量,此处为2 ``` ### ContainsKey和ContainsValue `ContainsKey()` 方法用于判断字典中是否包含指定的键,返回一个布尔值。 `ContainsValue()` 方法用于判断字典中是否包含指定的值,返回一个布尔值。 ``` bool hasAlice = ageDict.ContainsKey("Alice"); // 判断字典是否包含键"Alice" bool hasAge30 = ageDict.ContainsValue(30); // 判断字典是否包含值为30的元素 ``` 参考: https://blog.csdn.net/qq_21484461/article/details/132227303 原文出处:http://www.malaoshi.top/show_1GW1OtfmgBAd.html