介绍
在C#编程中,IDictionary<TKey, TValue> 和 Dictionary<TKey, TValue> 是处理键值对集合时常用的类型。下面将详细介绍它们的概念、区别及应用场景,并提供相应的代码示例。
见下面的两张身份证图片,观察区别,哪个身份证更加易于理解
“姓名”、“性别”就是key,与之对应的具体内容就是value
类比Java
IDictionary 相当于 MapDictionary 相当于 HashMap
1. IDictionary 接口
概念
- 定义:
IDictionary<TKey, TValue>是一个泛型接口,定义了操作键值对集合的基本方法和属性。 - 特点:
- 键必须唯一,且不能为
null(除非TKey是引用类型)。 - 值可以重复或为
null。 - 提供了添加、删除、查找元素等方法。
- 键必须唯一,且不能为
- 应用场景:当需要编写通用代码,支持不同字典实现时使用。
常用方法和属性
| 成员 | 描述 |
|---|---|
Add(key, value) |
添加键值对。 |
ContainsKey(key) |
检查是否包含指定键。 |
Remove(key) |
移除指定键的元素。 |
TryGetValue(key, out value) |
获取键对应的值(安全方式)。 |
this[key] |
通过索引器访问或设置值。 |
Keys |
获取所有键的集合。 |
Values |
获取所有值的集合。 |
2. Dictionary 类
概念
- 定义:
Dictionary<TKey, TValue>是IDictionary<TKey, TValue>的具体实现类,基于哈希表实现。 - 特点:
- 动态扩容,无需预先指定大小。
- 插入、查找和删除操作的时间复杂度接近 O(1)。
- 非线程安全(如需线程安全,可使用
ConcurrentDictionary)。
- 应用场景:需要高效存储和快速查找键值对的场景。
3. 核心区别
| IDictionary | Dictionary |
|---|---|
| 接口(不能直接实例化) | 具体类(可直接实例化) |
| 定义契约,不提供具体实现 | 提供基于哈希表的高效实现 |
| 用于抽象编程(依赖倒置原则) | 用于具体实现 |
例子
创建
要使用 Dictionary<TKey, TValue>,同样需要引入 System.Collections.Generic 命名空间。在创建字典时,需要指定键和值的类型,例如,如果我们希望以字符串作为键,以整数作为值,则创建一个 Dictionary<string, int> 类型的字典。
using System.Collections.Generic;
// 创建一个以字符串作为键,以整数作为值的字典
Dictionary<string, int> ageDict = new Dictionary<string, int>();
初始化
从C# 3.0 之后提供了初始化器,可以初始化Dictionary
Dictionary<string, int> ageDict = new Dictionary<string, int> {
{"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 item in ageDict)
{
Console.WriteLine($"{item.Key}: {item.Value}");
}
// 遍历键
foreach (var key in ageDict.Keys)
{
Console.WriteLine(key);
}
// 遍历值
foreach (var value in ageDict.Values)
{
Console.WriteLine(value);
}
常见问题
- 键为
null:若TKey为引用类型,插入null键会抛出ArgumentNullException。 - 重复键:插入重复键会抛出
ArgumentException,可先使用ContainsKey检查。 - 线程安全:
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

