# 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
#字典
#泛型集合
#集合
#进阶
