首页 游戏 软件 资讯 排行榜 专题
首页
编程语言
C#怎么使用Dictionary字典 C#如何用Dictionary存储键值对实现高效查找和遍历【基础】

C#怎么使用Dictionary字典 C#如何用Dictionary存储键值对实现高效查找和遍历【基础】

热心网友
68
转载
2026-05-05

C# Dictionary 使用指南:从泛型定义到线程安全,全面解析核心用法与最佳实践

C#怎么使用Dictionary字典 C#如何用Dictionary存储键值对实现高效查找和遍历【基础】

免费影视、动漫、音乐、游戏、小说资源长期稳定更新! 👉 点此立即查看 👈

Dictionary 初始化时必须指定泛型类型

在 C# 中直接声明 new Dictionary() 会导致编译失败。Dictionary 是一个强类型的泛型集合,必须明确指定键(TKey)和值(TValue)的具体类型。例如,创建字符串到用户对象的映射,应写作 new Dictionary()。避免使用 new Dictionary()new Dictionary() 这类写法,后者虽能编译,但会破坏类型安全并引发不必要的装箱拆箱性能损耗。

未指定泛型参数通常会引发编译错误 CS0305,或在运行时抛出 InvalidCastException 类型转换异常。

  • 键类型的选择原则:推荐使用不可变且已正确实现 GetHashCode()Equals() 方法的类型作为键,例如 stringintGuid 等,这些是理想的字典键类型。
  • 自定义类作为键的注意事项:若使用自定义类作为键,必须重写 GetHashCode()Equals() 方法,否则字典将基于对象引用进行相等性比较,导致查找逻辑错误。
  • 避免使用可变键:切勿使用内容可变的引用类型(如未重写相关方法的 List)作为键。键值一旦被修改,其哈希码可能改变,导致该键在字典中无法被正确检索。

添加和查找键值对必须注意 KeyNotFoundException

通过索引器直接访问值,如 dict[“abc”],是常见的错误用法。若键“abc”不存在,程序将抛出 KeyNotFoundException 异常,而非返回 null 或默认值。这在不确定键是否存在的业务场景中风险极高。

正确的字典值获取方式主要分为以下三种情况:

  • 场景一:明确知道键存在。可直接使用 dict[key],这种方式最为简洁且性能最佳,但前提是程序逻辑必须确保该键已被添加。
  • 场景二:不确定键是否存在,且需要获取对应值。强烈推荐使用 dict.TryGetValue(key, out value) 方法。它返回一个布尔值指示查找是否成功,并通过 out 参数返回找到的值。这种方法避免了异常抛出,且经过性能优化,是兼顾安全与效率的首选。
  • 场景三:仅需判断键是否存在,无需获取值。可使用 dict.ContainsKey(key) 方法。但需注意,其内部可能执行额外的哈希计算,通常比 TryGetValue 略慢。若非仅需判断存在性,更推荐使用 TryGetValue

以下是一个典型的安全取值示例:

if (users.TryGetValue(“U1001”, out var user))
{
    Console.WriteLine(user.Name);
}
else
{
    Console.WriteLine(“用户不存在”);
}

遍历 Dictionary 推荐用 foreach + KeyValuePair 而非 Keys/Values 分离

在需要同时遍历键和值时,应避免使用 foreach (var key in dict.Keys) { var val = dict[key]; ... } 这种模式。其问题在于,对每个键都会执行两次哈希查找(一次在 Keys 集合中,一次通过索引器),造成不必要的性能开销,且在并发修改时可能引发错误。

更高效且优雅的做法是直接遍历字典本身,它会返回一系列 KeyValuePair 结构体:

  • 标准遍历写法:使用 foreach (var kvp in dict),然后通过 kvp.Keykvp.Value 访问键值对。这是最清晰、最常用的方式。
  • 解构遍历写法(C# 7及以上):若追求代码简洁,可使用元组解构语法:foreach (var (id, user) in dict)。这种方式要求键值类型明确,使代码意图一目了然。
  • 应避免的写法:不要为了遍历而调用 dict.Keys.ToList() 或类似方法。这会创建不必要的中间集合,导致额外的内存分配,并丢失字典原有的结构语义。

Dictionary 不是线程安全的,多线程读写必须加锁或换 ConcurrentDictionary

这是一个关键的安全警告:标准的 Dictionary 类不是线程安全的。当多个线程同时执行添加、删除或某些读取操作时,可能导致其内部数据结构损坏,进而引发 InvalidOperationException 异常或返回错误数据。即使是“读多写少”的场景,只要存在任何写操作,就必须对普通 Dictionary 进行同步保护。

请注意,即便只是并发读取,在字典内部因容量不足而触发扩容重建时,也可能导致不可预知的问题。

处理多线程并发访问字典,主要有两种主流方案:

  • 手动同步(使用锁):使用 lock 语句块包裹所有对字典的读写操作。建议使用一个私有的、只读的对象作为锁对象,避免直接锁定 this 或字典实例本身,以降低死锁风险。
  • 使用线程安全集合:直接替换为 ConcurrentDictionary。该类内部采用了更精细的锁机制(如分段锁),使得大多数读操作可以无锁进行,写操作的锁竞争也更小,性能更优。但需注意,其 GetOrAddAddOrUpdate 等方法接收的工厂委托可能会被多次执行,因此不应在委托内编写具有副作用的逻辑。
来源:https://www.php.cn/faq/2316354.html
免责声明: 游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。

相关攻略

c#如何使用RabbitMQ_c#RabbitMQ新手必看入门教程
编程语言
c#如何使用RabbitMQ_c#RabbitMQ新手必看入门教程

C 开发RabbitMQ:从基础连接到生产级实践的避坑指南 在C 项目中集成RabbitMQ消息队列时,一个关键决策是选择客户端库。虽然RabbitMQ Client是官方核心NuGet包,但许多开发者会考虑使用像EasyNetQ这样的高级封装库以简化操作。然而,对于希望深入理解RabbitMQ工作

热心网友
05.05
c#如何连接InfluxDB_c#InfluxDB的正确用法与注意事项
编程语言
c#如何连接InfluxDB_c#InfluxDB的正确用法与注意事项

C 连接 InfluxDB 的完整教程:从入门到精通,避开常见陷阱 对于 C 开发者而言,连接 InfluxDB 时遇到认证失败或查询无数据等问题,往往源于版本与客户端选择错误。本文的核心结论是:连接 InfluxDB 2 x 必须使用官方的 InfluxDB Client NuGet 包,并采

热心网友
05.05
C#怎么使用Dictionary字典 C#如何用Dictionary存储键值对实现高效查找和遍历【基础】
编程语言
C#怎么使用Dictionary字典 C#如何用Dictionary存储键值对实现高效查找和遍历【基础】

C Dictionary 使用指南:从泛型定义到线程安全,全面解析核心用法与最佳实践 Dictionary 初始化时必须指定泛型类型 在 C 中直接声明 new Dictionary() 会导致编译失败。Dictionary 是一个强类型的泛型集合,必须明确指定键(TKey)和值(TValue)

热心网友
05.05
c#如何使用HslCommunication库_c#HslCommunication库快速上手实战教程
编程语言
c#如何使用HslCommunication库_c#HslCommunication库快速上手实战教程

C HslCommunication库使用指南:工业通信快速入门与实战技巧 在工业自动化与智能制造项目中,利用C 实现上位机与PLC的稳定通信是一项核心技能。HslCommunication库凭借其广泛支持的工业协议与相对简洁的API设计,已成为众多 NET开发者的首选工具。然而,从基础功能实现到

热心网友
05.05
C#怎么操作Timer定时器控件 C#WinForms Timer和Threading.Timer的区别和使用场景【控件】
编程语言
C#怎么操作Timer定时器控件 C#WinForms Timer和Threading.Timer的区别和使用场景【控件】

C Timer定时器控件操作指南:WinForms Timer与Threading Timer核心区别与应用场景详解 在C 编程中,正确选择定时器控件至关重要。WinForms Timer、Threading Timer以及使用Task Delay模拟的循环任务,虽然都能实现定时执行功能,但其底层

热心网友
05.05

最新APP

宝宝过生日
宝宝过生日
应用辅助 04-07
台球世界
台球世界
体育竞技 04-07
解绳子
解绳子
休闲益智 04-07
骑兵冲突
骑兵冲突
棋牌策略 04-07
三国真龙传
三国真龙传
角色扮演 04-07

热门推荐

荣耀400pro关机要按几秒
电脑教程
荣耀400pro关机要按几秒

荣耀400 Pro正确关机全指南:从常规操作到故障应对详解 需要关闭您的荣耀400 Pro手机?日常操作其实非常简便。只需长按位于机身右侧的电源键约3秒钟,屏幕上便会浮现一个简洁的半透明菜单,其中明确列出了“关机”、“重启”以及“紧急呼叫”选项。直接点击“关机”,系统将启动一次10秒的安全倒计时,随

热心网友
05.06
红米K30Pro如何拆后盖胶怎么清理
电脑教程
红米K30Pro如何拆后盖胶怎么清理

红米K30 Pro后盖拆解教程:专业工具与细致手法的完美结合 红米K30 Pro的后盖采用了高强度背胶配合隐藏式螺丝的双重固定设计,想要实现无损拆解,绝非依靠蛮力可以完成。整个操作流程对加热温度、撬启手法以及清洁标准都有严格要求,任何环节的疏忽都可能导致部件损伤。具体而言,其后盖边缘使用了耐高温的工

热心网友
05.06
三星zflip电池百分比需要root吗
电脑教程
三星zflip电池百分比需要root吗

无需Root权限:三星Galaxy Z Flip系列电量数字显示设置全解析 很多三星折叠屏手机用户都想知道,如何在状态栏直接查看精确的电池百分比数字,是否必须获取Root权限才能实现?实际上完全不需要。三星自Galaxy Z Flip 5、Z Flip 4等主流机型开始,已在系统层面内置了这一实用功

热心网友
05.06
笔记本开机自检时能看到DDR3或DDR4吗
电脑教程
笔记本开机自检时能看到DDR3或DDR4吗

笔记本开机自检信息虽不直接标注“DDR3”或“DDR4”,但联想、戴尔、华硕等品牌BIOS画面常以“PC3-”或“PC4-”编码间接揭示内存代际。UEFI自检显示的内存频率(如2400MHz 3200MHz)结合JEDEC规范可辅助推断:PC3对应DDR3,PC4对应DDR4。更高精度的识别方案包括

热心网友
05.06
空调制冷但不太凉是压缩机问题吗?
电脑教程
空调制冷但不太凉是压缩机问题吗?

空调制冷不足怎么办?先别急着维修压缩机,这些问题更常见 夏天开空调却感觉不够凉爽?很多朋友的第一反应是压缩机坏了,其实压缩机故障的概率相对较低。根据维修行业的大数据统计,绝大多数制冷效果不佳的情况,源于几个容易被忽略的日常维护与环境因素。滤网积尘、制冷剂泄漏、外机散热不良才是真正的高发原因。盲目更换

热心网友
05.06