Files
2026-06-22 22:11:42 +08:00

410 lines
8.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Dictionary
概念:
`Dictionary<TKey, TValue>` 是 C# 提供的==泛型键值对集合==
它通过键 `key` 来快速查找值 `value`
简单理解:
像一本字典
用“词”查“解释”
`key``value`
命名空间:
```csharp
using System.Collections.Generic;
```
----
# 通常用法
1. 保存键值对数据
2. 通过唯一键快速查找对应值
3. 根据 `id`、名字、编号等信息管理对象
4. 替代早期非泛型键值对集合 `Hashtable`
实际开发中:
`Dictionary<TKey, TValue>` 非常常用
只要需求是“通过 key 快速找到 value”
通常都可以先考虑它
----
# 语法
创建:
```csharp
Dictionary<string, int> dict = new Dictionary<string, int>();
```
添加:
```csharp
dict.Add("语文", 90);
```
通过键取值:
```csharp
int score = dict["语文"];
```
修改:
```csharp
dict["语文"] = 95;
```
数量:
```csharp
dict.Count
```
----
# 基础案例
```csharp
using System;
using System.Collections.Generic;
Dictionary<string, int> scores = new Dictionary<string, int>();
scores.Add("语文", 90);
scores.Add("数学", 95);
scores.Add("英语", 88);
Console.WriteLine(scores["语文"]);
Console.WriteLine(scores["数学"]);
Console.WriteLine(scores["英语"]);
Console.WriteLine(scores.Count);
```
输出:
```text
90
95
88
3
```
理解:
1. `"语文"``"数学"``"英语"` 是键
2. `90``95``88` 是值
3. 通过 key 能快速找到对应 value
----
# Add 和索引器
使用 `Add` 添加:
```csharp
Dictionary<string, int> dict = new Dictionary<string, int>();
dict.Add("hp", 100);
dict.Add("mp", 50);
```
使用索引器新增或修改:
```csharp
dict["atk"] = 20; // key 不存在时,新增
dict["atk"] = 25; // key 已存在时,修改
```
区别:
1. `Add` 遇到重复 key 会报错
2. `dict[key] = value` 遇到重复 key 会覆盖旧值
----
# 增删查改
增加:
```csharp
dict.Add("def", 10);
```
删除:
```csharp
dict.Remove("def");
dict.Clear();
```
查找键:
```csharp
bool hasHp = dict.ContainsKey("hp");
```
查找值:
```csharp
bool hasValue = dict.ContainsValue(100);
```
修改:
```csharp
dict["hp"] = 120;
```
取值:
```csharp
int hp = dict["hp"];
```
----
# TryGetValue 很常用
直接取值:
```csharp
int hp = dict["hp"];
```
问题:
如果 key 不存在
会报错
更稳的写法:
```csharp
if (dict.TryGetValue("hp", out int hp))
{
Console.WriteLine(hp);
}
else
{
Console.WriteLine("没有这个键");
}
```
说明:
1. `TryGetValue` 会返回 `true``false`
2. 如果找到 key,就把对应值放进 `out` 变量
3. 如果项目里经常“先查再取”,`TryGetValue` 很实用
----
# 遍历
遍历键值对:
```csharp
Dictionary<string, int> dict = new Dictionary<string, int>();
dict.Add("语文", 90);
dict.Add("数学", 95);
foreach (KeyValuePair<string, int> item in dict)
{
Console.WriteLine(item.Key + " : " + item.Value);
}
```
只遍历键:
```csharp
foreach (string key in dict.Keys)
{
Console.WriteLine(key);
}
```
只遍历值:
```csharp
foreach (int value in dict.Values)
{
Console.WriteLine(value);
}
```
注意:
复习时不要把 `Dictionary` 当成“按下标顺序排列的列表”
它的核心用途是通过 key 查 value
----
# key 不能重复
错误写法:
```csharp
Dictionary<string, int> dict = new Dictionary<string, int>();
dict.Add("hp", 100);
dict.Add("hp", 200);
```
原因:
`Dictionary` 中的 key 必须唯一
重复添加同一个 key 会报错
如果想修改旧值:
```csharp
dict["hp"] = 200;
```
----
# key 一般不能为 null
错误写法:
```csharp
Dictionary<string, int> dict = new Dictionary<string, int>();
// dict.Add(null, 100);
```
原因:
`Dictionary` 的 key 不能为 `null`
补充:
如果 `TValue` 是引用类型或可空类型
value 可以是 `null`
示例:
```csharp
Dictionary<string, string> dict = new Dictionary<string, string>();
dict["name"] = null;
```
----
# 和 Hashtable 的区别
`Hashtable`
非泛型
key 和 value 都按 `object` 处理
取值时常常需要强制类型转换
`Dictionary<TKey, TValue>`
泛型
key 和 value 类型明确
编译期就能检查类型错误
使用起来更安全,更常见
对比表:
| 对比点 | `Hashtable` | `Dictionary<TKey, TValue>` |
|---|---|---|
| 类型 | 非泛型 | 泛型 |
| 键和值 | `object` | 指定类型 |
| 类型安全 | 较弱 | 更强 |
| 取值 | 常要强转 | 一般不用强转 |
| 推荐程度 | 主要用于学习旧集合 | 实际开发常用 |
----
# 和 List 的区别
| 对比点 | `List<T>` | `Dictionary<TKey, TValue>` |
|---|---|---|
| 存储方式 | 单个元素 | 键值对 |
| 查找方式 | 常用下标 | 常用 key |
| key | 没有 | 必须唯一 |
| 适合场景 | 一组同类型数据 | 根据唯一键查数据 |
一句话:
`List<T>` 更像“列表”
`Dictionary<TKey, TValue>` 更像“字典”
----
# 基础案例:角色表
```csharp
using System;
using System.Collections.Generic;
class Player
{
public string Name;
public int Level;
public Player(string name, int level)
{
Name = name;
Level = level;
}
}
class Program
{
static void Main(string[] args)
{
Dictionary<int, Player> players = new Dictionary<int, Player>();
players.Add(1001, new Player("小明", 10));
players.Add(1002, new Player("小红", 12));
players.Add(1003, new Player("小刚", 8));
if (players.TryGetValue(1002, out Player player))
{
Console.WriteLine(player.Name + " " + player.Level);
}
}
}
```
输出:
```text
小红 12
```
理解:
1. `1001``1002``1003` 是玩家编号
2. 通过编号可以快速找到对应玩家对象
3. 这种“编号 -> 对象”的场景非常适合用 `Dictionary`
----
# 常用成员
```csharp
Dictionary<string, int> dict = new Dictionary<string, int>();
dict.Add("A", 1);
dict["B"] = 2;
Console.WriteLine(dict.Count);
Console.WriteLine(dict.ContainsKey("A"));
Console.WriteLine(dict.ContainsValue(2));
dict.Remove("A");
dict.Clear();
```
常用方法 / 成员:
1. `Add(TKey key, TValue value)`:添加键值对
2. `Remove(TKey key)`:删除指定 key
3. `Clear()`:清空
4. `ContainsKey(TKey key)`:判断 key 是否存在
5. `ContainsValue(TValue value)`:判断 value 是否存在
6. `TryGetValue(TKey key, out TValue value)`:安全取值
7. `Keys`:获取所有键
8. `Values`:获取所有值
9. `Count`:键值对数量
10. `dict[key]`:通过 key 取值或赋值
----
# 注意
1. `Dictionary<TKey, TValue>``System.Collections.Generic` 命名空间中
2. 它是泛型键值对集合
3. key 必须唯一
4. `Add` 遇到重复 key 会报错
5. `dict[key] = value` 可以新增,也可以覆盖旧值
6. 用不存在的 key 直接取值可能报错
7. 更稳的取值方式通常是 `TryGetValue`
8. 它最核心的优势是“通过 key 快速找 value”
----
# 易错点
1. 不要把 `Dictionary` 当数组或 `List<T>` 来用
2. 不要默认 key 一定存在
3. `ContainsKey` 判断的是键,不是值
4. `ContainsValue` 可以用,但实际开发里更常关心 key
5. 重复 `Add` 同一个 key 会报错
错误示例:
```csharp
Dictionary<string, int> dict = new Dictionary<string, int>();
dict.Add("hp", 100);
// Console.WriteLine(dict["mp"]);
```
原因:
`"mp"` 这个 key 不存在
直接取值可能报错
----
# 一句话记忆
==Dictionary<TKey, TValue> 是通过唯一 key 快速查找 value 的泛型键值对集合。==
再压缩一点:
==List 用下标找,Dictionary 用 key 找。==
----
# 面试/复习时怎么说
可以这样答:
`Dictionary<TKey, TValue>` 是 C# 中非常常用的泛型键值对集合,适合通过唯一 key 快速查找 value。
它的 key 不能重复,常用操作有 `Add``Remove``ContainsKey``TryGetValue`
相比 `Hashtable``Dictionary` 类型更安全,不需要频繁强制类型转换,所以实际开发中更常用。”
----
引用:
1. Microsoft Learn: [Dictionary<TKey,TValue> Class](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.dictionary-2?view=net-9.0)
2. Microsoft Learn: [Dictionary<TKey,TValue>.TryGetValue Method](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.dictionary-2.trygetvalue?view=net-9.0)
3. Microsoft Learn: [System.Collections.Generic Namespace](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic?view=net-9.0)
#Dictionary
#字典
#泛型集合
#集合
#进阶