c#如何使用Hashtable_c#Hashtable深入理解与底层原理

浅丽小哥_7885

浅丽小哥_7885

2026-04-11

769人浏览

原创

现代C#项目中不建议直接使用Hashtable,除非维护老代码或有明确线程安全需求;其非泛型设计导致装箱拆箱开销大、类型转换风险高,Dictionary在性能、类型安全和内存效率上全面优于它。

c#如何使用hashtable_c#hashtable深入理解与底层原理

现代 C# 项目里,不建议直接用 Hashtable,除非你在维护老代码或有明确线程安全需求。 它的非泛型设计、装箱拆箱开销、运行时类型转换风险,已经让 Dictionary<tkey tvalue></tkey> 成为更优解。但理解它,能帮你读懂遗留系统、排查类型转换异常、甚至看懂 ConcurrentDictionary 的演进逻辑。

为什么 Hashtable.Add() 会抛出 ArgumentException

常见错误是往同一个 Hashtable 中重复添加相同 key:

ht.Add("id", 1001);
ht.Add("id", 1002); // ⚠️ 这里直接炸:ArgumentException: An entry with the same key already exists.

原因很简单:Hashtable 要求 key 唯一且不可变。它内部用 key.GetHashCode() 算哈希值,再映射到桶(bucket)位置;重复 key 意味着哈希冲突处理失败,直接拒绝插入。

  • 检查是否误用了 Add() 而非 [key] = value(后者是覆盖行为)
  • 注意字符串 key 的大小写敏感性:"Name" 和 "name" 是两个不同 key
  • 自定义对象作 key 时,必须重写 GetHashCode() 和 Equals(),否则默认引用比较会导致“看似相同却无法命中”

取值时强制转换 (string)ht["name"] 总报 InvalidCastException 怎么办

这是 Hashtable 最典型的运行时陷阱:它存的是 object,取出来必须手动转回原类型。一旦类型不匹配,就崩。

比如你存了 ht["count"] = 42;(int 装箱成 object),但取的时候写 string s = (string)ht["count"]; —— 直接抛 InvalidCastException。

C#
C#

"避开 C# 常见错误——空陷阱、异步陷阱、LINQ 陷阱及资源泄漏。"

下载
  • 用 ContainsKey("key") 先判断 key 是否存在,避免 null 引发 NullReferenceException
  • 用 as 安全转换代替强制转换:string? name = ht["name"] as string;,失败返回 null 而非异常
  • 对值类型(int、bool 等),优先用可空类型 + as 或 Convert.ToInt32() 防装箱失败

Hashtable.Synchronized() 真的安全吗

Hashtable.Synchronized(new Hashtable()) 返回一个线程安全包装器,但它只保证单个操作原子性,比如 Add() 或 ContainsKey() 不会被并发打断。但它不保证复合操作的原子性。

例如下面这段代码仍是线程不安全的:

if (!syncTable.ContainsKey("status")) {
    syncTable["status"] = "running"; // ⚠️ 两步:查 + 写,中间可能被其他线程插入同 key
}
  • 这种“先查后写”场景,要用 lock 手动同步,或改用 ConcurrentDictionary
  • Synchronized() 包装器性能较差,每次调用都加锁,高并发下成为瓶颈
  • 现代替代方案是 ConcurrentDictionary<string object></string>,它支持 GetOrAdd()、AddOrUpdate() 等原子复合操作

Hashtable 和 Dictionary 的性能差在哪

差距主要来自装箱/拆箱和类型检查:

  • 往 Hashtable 存 int:触发装箱 → 新建 object 实例 → 占内存、GC 压力大
  • 从 Hashtable 取 int:触发拆箱 → 类型校验 + 复制值 → 多一次运行时开销
  • Dictionary<string int></string> 全程在栈/堆上操作原生类型,无装箱,编译器还能做泛型特化优化
  • 实测:百万级整数读写,Dictionary 比 Hashtable 快 30%~50%,内存占用低 20%+

真正需要关注的不是“怎么用 Hashtable 更快”,而是“有没有必要继续用它”。除非你在对接 .NET Framework 1.1 时代的 COM 组件,或者调试一段无法修改的旧 ASP.NET Web Forms 代码,否则请直接切到 Dictionary 或 ConcurrentDictionary。

相关专题

更多
c#是什么意思
c#是什么意思

C#是一种通用的面向对象编程语言,它在.NET框架上运行,可用于开发各种类型的应用程序。本专题为大家提供c#相关的各种文章、以及下载和课程。

2023.08.08

1052

5

什么是c#
什么是c#

C#(读作C Sharp)是一种现代的、通用的、面向对象的编程语言。它由微软公司开发,于2000年首次发布,主要用于开发Windows桌面应用程序、Web应用程序、移动应用程序以及游戏开发等领域。C#是一种类型安全和托管的编程语言,它结合了C++的强大性能和C语言的简单易学特点,并引入了许多新的特性和概念,如委托、属性、泛型和异步编程等,以提高开发效率和代码可维护性。

2023.08.31

3051

3

C#中base关键字的用法
C#中base关键字的用法

在C#中,base关键字用于访问当前类的基类成员,这包括基类的字段、属性、方法、构造函数、索引器以及事件。想了解更多C#的相关内容,可以阅读本专题下面的文章。

2024.03.13

905

8

C#Task用法
C#Task用法

Task在C#中是用于表示异步操作的对象,它位于System.Threading.Tasks命名空间中。想了解更多C#中各种用法的相关内容,可以阅读本专题下面的文章。

2024.03.14

2635

11

C# 并发与异步编程
C# 并发与异步编程

本专题系统讲解 C# 异步编程与并发控制,重点介绍 async 和 await 关键字、Task 类、线程池管理、并发数据结构、死锁与线程安全问题。通过多个实战项目,帮助学习者掌握 如何在 C# 中编写高效的异步代码,提升应用的并发性能与响应速度。

2026.02.03

332

18

C# 多线程与异步编程
C# 多线程与异步编程

本专题深入讲解 C# 中多线程与异步编程的核心概念与实战技巧,包括线程池管理、Task 类的使用、async/await 异步编程模式、并发控制与线程同步、死锁与竞态条件的解决方案。通过实际项目,帮助开发者掌握 如何在 C# 中构建高并发、低延迟的异步系统,提升应用性能和响应速度。

2026.02.06

409

20

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

2026.03.11

631

24

C# Unity游戏开发与ECS架构实践
C# Unity游戏开发与ECS架构实践

本专题聚焦 C# 在 Unity 游戏开发中的应用,系统讲解 ECS(Entity-Component-System)架构设计、游戏对象管理、性能优化与内存控制策略。通过实际游戏案例,帮助开发者构建高性能、结构清晰的游戏系统,提高游戏开发效率与运行性能。

2026.04.13

329

20

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习