C# 词典与x27的关系;存储值的存储桶的s键哈希代码和索引

C# 词典与x27的关系;存储值的存储桶的s键哈希代码和索引,c#,C#,Wiki说(据我所知),每当我向字典添加一个项目时,系统都会计算哈希代码(通过调用GetHashCode)。然后,系统使用哈希代码查找一个存储我的值的存储桶 请解释一下在bucket数组中查找哈希代码和索引之间关系的逻辑,我的值将通过字典存储在该数组中 想象一下,当我创建一个字典并向其中添加一个对象时,谁的GetHashCode返回值1000000 这是否意味着InsideDictionary将创建一个包含1000000个元素的数组,并将我的对象存储在索引99999999处 如果这一假设是正确的

Wiki说(据我所知),每当我向字典添加一个项目时,系统都会计算哈希代码(通过调用GetHashCode)。然后,系统使用哈希代码查找一个存储我的值的存储桶

请解释一下在bucket数组中查找哈希代码和索引之间关系的逻辑,我的值将通过字典存储在该数组中

想象一下,当我创建一个字典并向其中添加一个对象时,谁的GetHashCode返回值1000000

这是否意味着InsideDictionary将创建一个包含1000000个元素的数组,并将我的对象存储在索引99999999处


如果这一假设是正确的,那么让这么大的数组只存储一个值有什么意义呢。

幸运的是,您的假设是不正确的。如果是这样的话,它们实际上就不是bucket,而是一个索引可访问的对象数组。如果您的hashcode保证是唯一的,那么这对于O(1)查找可能是好的,但事实并非如此——事实上,hashcode保证不是唯一的。不能将Int64的所有可能值映射到唯一的Int32哈希代码中。这不是哈希代码的用途

相反,字典初始化一个较小的bucket数组,然后使用简单的模运算来查找bucket。(摘自)

这意味着,例如,如果有10个bucket,它将得到hashcode除以10的剩余部分。如果您的哈希算法做得很好,这意味着哈希代码遵循标准分布,这意味着对于足够大的n个项,任何n个项都可能在桶之间平均分配


至于初始化了多少个bucket,这个数字将是第一个素数,它高于在ctor中传递的容量,或者0()。如果这导致过多的哈希冲突,它将自动展开,每次跳到下一个素数,直到稳定。

没有记录关系,对CLI的更新可能会改变它。各种工具都允许反编译程序集,因此您可以进行反编译。但是,任何对细节的依赖都有可能导致随机破坏。这听起来像是一个XY问题:您为什么想知道?否。索引将根据哈希代码和表大小的组合(例如,
hashCode%table.Count
)以及解决任何冲突的结果来计算。您可以从概念上看到实现,哈希桶可能只是一个参考点,指示给定索引或索引范围的值可以存储在哪里。它不一定要映射到直接物理存储。它还可以实现一个“位置数组”——如果一个实现提供了一个默认值,比如说10个bucket,那么如果键/值对为空,那么每个bucket只能是一个链表。
 int targetBucket = hashCode % buckets.Length;