为何在 C# 中更倾向使用 Dictionary 而非 Hashtable

为何在 C# 中更倾向使用 Dictionary 而非 Hashtable

技术背景

在 C# 开发里,Dictionary<TKey, TValue>Hashtable 都是用于存储键值对的数据结构,其内部均为哈希表,可依据键快速访问数据。不过,由于本质上 Dictionary<TKey, TValue> 是泛型类型,而 Hashtable 是非泛型类型,这使得它们在性能、类型安全性等方面存在诸多差异。

实现步骤

Dictionary 示例代码

1
2
3
var customers = new Dictionary<string, Customer>();
customers.Add("Ali G", new Customer());
Customer customer = customers["Ali G"];

Hashtable 示例代码

1
2
3
var customers = new Hashtable();
customers.Add("Ali G", new Customer());
Customer customer = customers["Ali G"] as Customer;

差异对比

1. 泛型与否

  • Dictionary 为泛型类型,创建时需指定键和值的类型,从而确保在访问内容时类型安全。
  • Hashtable 属于非泛型类型,会将键和值当作 Object 类型处理,因此在使用时可能需要进行类型转换。

2. 线程安全

  • Dictionary 需要自行实现线程同步。
  • Hashtable 借助 Synchronized() 方法提供线程安全版本。

3. 枚举项

  • Dictionary 枚举项为 KeyValuePair
  • Hashtable 枚举项是 DictionaryEntry

4. 版本与命名空间

  • Dictionary 是较新的类(.NET 2.0 及以上),位于 System.Collections.Generic 命名空间。
  • Hashtable 是较旧的类(自 .NET 1.0 开始),处在 System.Collections 命名空间。

5. 键不存在时的处理方式

  • Dictionary 对不存在的键进行请求时会抛出异常。
  • Hashtable 对不存在的键进行请求时返回 null

6. 值类型性能

  • Dictionary 对于值类型可能会稍快一些。
  • Hashtable 对于值类型会稍慢(需要进行装箱/拆箱操作)。

相似点

  • 二者内部皆为哈希表,能依据键快速访问多项目数据。
  • 都需要不可变且唯一的键。
  • 二者的键均需要自身的 GetHashCode() 方法。

替代的 .NET 集合

  1. ConcurrentDictionary:线程安全,可由多个线程并发安全访问。
  2. HybridDictionary:针对不同数量的项目进行了性能优化。
  3. OrderedDictionary:可通过整数索引访问值,按添加顺序排列。
  4. SortedDictionary:项会自动排序。
  5. StringDictionary:类型安全且针对字符串进行了优化(现在已弃用,推荐使用 Dictionary<string, string>)。

碰撞解决策略

  • Hashtable 采用的是再哈希(rehashing)技术。存在一组不同的哈希函数 H1 ... Hn,插入或检索项时,最初会使用 H1 哈希函数,若发生碰撞则尝试 H2,依此类推。
  • Dictionary 采用的是链地址法(chaining)技术。发生碰撞时,会利用一个辅助数据结构来保存所有碰撞元素。具体而言,Dictionary 中的每个槽都有一个元素数组,碰撞时会将碰撞元素添加到该槽的列表头部。

最佳实践

  • 若需要类型安全且不考虑线程同步,优先选用 Dictionary
  • 若要线程安全,可选用 Hashtable 或者 ConcurrentDictionary
  • 若要根据插入顺序访问元素,可使用 OrderedDictionary

常见问题

1. Dictionary 线程不安全怎么办?

若在多线程环境下使用 Dictionary,则需要自行实现线程同步。也可以使用 ConcurrentDictionary 来替代。

2. Hashtable 的线程安全版本性能如何?

Hashtable 的线程安全版本(通过 Synchronized() 方法)在每次添加或移除操作时都会锁定整个集合,这对大型集合来说可能会导致显著的性能下降,且在设计上并不能完全避免竞态条件。

3. DictionaryHashtable 对值类型的性能差异是怎样的?

Hashtable 在存储或检索值类型时需要进行装箱/拆箱操作,这会影响其性能。而 Dictionary 对于值类型无需进行装箱/拆箱操作,因此性能可能更好。


为何在 C# 中更倾向使用 Dictionary 而非 Hashtable
https://119291.xyz/posts/why-dictionary-preferred-over-hashtable-in-csharp/
作者
ww
发布于
2025年5月30日
许可协议