# Hashtable
概念：
	`Hashtable` 是 C# 提供的一个==非泛型键值对集合==
	它通过键 `key` 来查找值 `value`

简单理解：
	像一本字典
	用“词”查“解释”
	用 `key` 查 `value`

命名空间：
```csharp
using System.Collections;
```

----
# 通常用法
1. 保存键值对数据
2. 通过唯一键快速查找对应值
3. 学习哈希表这种数据结构
4. 理解 `Dictionary<TKey, TValue>` 之前的非泛型写法

实际开发中：
	新代码更推荐使用 `Dictionary<TKey, TValue>`
	`Hashtable` 主要用于学习非泛型键值对集合

----
# 语法
创建：
```csharp
Hashtable table = new Hashtable();
```

添加：
```csharp
table.Add(键, 值);
```

通过键取值：
```csharp
object value = table[键];
```

修改：
```csharp
table[键] = 新值;
```

数量：
```csharp
table.Count
```

----
# 基础案例
```csharp
using System;
using System.Collections;

Hashtable table = new Hashtable();

table.Add("name", "小明");
table.Add("age", 18);
table.Add("isVip", true);

Console.WriteLine(table["name"]);
Console.WriteLine(table["age"]);
Console.WriteLine(table["isVip"]);
```

理解：
1. `"name"`、`"age"`、`"isVip"` 是键
2. `"小明"`、`18`、`true` 是值
3. 通过键可以找到对应的值

----
# Add 和索引器
使用 `Add` 添加：
```csharp
Hashtable table = new Hashtable();

table.Add("id", 1001);
table.Add("name", "小明");
```

使用索引器添加或修改：
```csharp
table["score"] = 90;     // 如果 key 不存在，就是新增
table["score"] = 100;    // 如果 key 已存在，就是修改
```

区别：
1. `Add` 遇到重复键会报错
2. `table[key] = value` 遇到重复键会覆盖旧值

----
# 增删查改
增加：
```csharp
table.Add("level", 10);
```

删除：
```csharp
table.Remove("level");
table.Clear();
```

查找键：
```csharp
bool hasName = table.ContainsKey("name");
```

查找值：
```csharp
bool hasValue = table.ContainsValue("小明");
```

修改：
```csharp
table["name"] = "小红";
```

取值：
```csharp
string name = (string)table["name"];
```

----
# 遍历
遍历键值对：
```csharp
Hashtable table = new Hashtable();

table.Add("name", "小明");
table.Add("age", 18);

foreach (DictionaryEntry item in table)
{
	Console.WriteLine(item.Key + " : " + item.Value);
}
```

只遍历键：
```csharp
foreach (object key in table.Keys)
{
	Console.WriteLine(key);
}
```

只遍历值：
```csharp
foreach (object value in table.Values)
{
	Console.WriteLine(value);
}
```

注意：
	`Hashtable` 的遍历顺序不保证等于添加顺序

----
# key 不能重复
错误写法：
```csharp
Hashtable table = new Hashtable();

table.Add("name", "小明");
table.Add("name", "小红");
```

原因：
	`Hashtable` 中的 key 必须唯一
	重复添加同一个 key 会报错

如果想修改旧值：
```csharp
table["name"] = "小红";
```

----
# key 不能是 null
错误写法：
```csharp
Hashtable table = new Hashtable();

table.Add(null, "值");
```

原因：
	`Hashtable` 的 key 不能为 `null`

但是 value 可以是 `null`：
```csharp
table.Add("data", null);
```

----
# 取值时要判断 key 是否存在
```csharp
Hashtable table = new Hashtable();
table.Add("name", "小明");

if (table.ContainsKey("name"))
{
	string name = (string)table["name"];
	Console.WriteLine(name);
}
```

为什么要判断：
1. key 不存在时，`table[key]` 可能拿到 `null`
2. value 本身也可能是 `null`
3. 用 `ContainsKey` 可以区分“没有这个键”和“这个键的值是 null”

----
# 取值时要类型转换
```csharp
Hashtable table = new Hashtable();
table.Add("age", 18);

int age = (int)table["age"];
```

原因：
	非泛型 `Hashtable` 的 key 和 value 都是按 `object` 处理
	取出来后通常需要强制类型转换

如果类型转错：
```csharp
string age = (string)table["age"];
```

会出错，因为 `"age"` 对应的值实际是 `int`。

----
# 和 ArrayList 的区别
| 对比点 | ArrayList | Hashtable |
|---|---|---|
| 存储方式 | 单个元素 | 键值对 |
| 访问方式 | 通过下标 | 通过 key |
| key 是否存在 | 没有 key | key 必须唯一 |
| 常见用途 | 普通列表 | 字典式查找 |
| 泛型替代 | `List<T>` | `Dictionary<TKey, TValue>` |

----
# 常见错误
错误1：重复 Add 同一个 key
```csharp
table.Add("id", 1);
table.Add("id", 2);
```

应该改成：
```csharp
table["id"] = 2;
```

----
错误2：以为 Hashtable 有添加顺序

实际：
	`Hashtable` 是根据 key 的哈希来组织数据
	遍历顺序不保证是添加顺序

----
错误3：取值后忘记强转
```csharp
int age = table["age"];
```

应该写：
```csharp
int age = (int)table["age"];
```

----
# 注意
1. `Hashtable` 在 `System.Collections` 命名空间中
2. `Hashtable` 是非泛型键值对集合
3. key 不能重复
4. key 不能是 `null`
5. value 可以是 `null`
6. `Add` 重复 key 会报错
7. `table[key] = value` 可以新增，也可以覆盖旧值
8. 遍历顺序不保证等于添加顺序
9. 新项目通常优先使用 `Dictionary<TKey, TValue>`

----
# 一句话记忆
==Hashtable 是用 key 找 value 的非泛型键值对集合。==

再压缩一点：
==ArrayList 靠下标找，Hashtable 靠 key 找。==

----
# 面试/复习时怎么说
可以这样答：

“Hashtable 是 `System.Collections` 命名空间下的非泛型键值对集合，通过唯一 key 查找 value。  
它的 key 不能重复，也不能为 null；value 可以为 null。  
因为 key 和 value 都按 object 处理，所以取值时通常需要强制类型转换。新项目中一般更推荐使用泛型集合 `Dictionary<TKey, TValue>`。”

----
引用：
1. Microsoft Learn: [Hashtable Class](https://learn.microsoft.com/dotnet/api/system.collections.hashtable?view=net-9.0)
2. Microsoft Learn: [Hashtable.Add Method](https://learn.microsoft.com/en-us/dotnet/api/system.collections.hashtable.add?view=net-9.0)
3. Microsoft Learn: [Hashtable.Item Property](https://learn.microsoft.com/en-us/dotnet/api/system.collections.hashtable.item?view=net-9.0)
4. Microsoft Learn: [System.Collections Namespace](https://learn.microsoft.com/en-us/dotnet/api/system.collections?view=net-9.0)

#Hashtable
#哈希表
#集合
#进阶
