C# 为什么字典键是不可变的?

C# 为什么字典键是不可变的?,c#,dictionary,key,immutability,C#,Dictionary,Key,Immutability,问了一个问题,为什么他们要求在字典中使用不可变对象作为键 当我最近使用一个字典时,这个问题实际上进入了我的脑海,它显然不是为了哈希表的目的,而是为了将Xml节点对象作为键。然后,我在使用过程中多次更新节点 那么,“使用不可变键”到底意味着什么呢?当您将一个键插入哈希表时,哈希表会询问该键的哈希代码,并记住它以及键本身和相关值。稍后执行查找时,哈希表会询问要查找的键以查找其哈希代码,并且可以非常快速地找到表中具有相同哈希代码的所有键 只要哈希表中的键在其整个生命周期中都保持相同的哈希代码,这一切都

问了一个问题,为什么他们要求在字典中使用不可变对象作为键

当我最近使用一个字典时,这个问题实际上进入了我的脑海,它显然不是为了哈希表的目的,而是为了将Xml节点对象作为键。然后,我在使用过程中多次更新节点


那么,“使用不可变键”到底意味着什么呢?

当您将一个键插入哈希表时,哈希表会询问该键的哈希代码,并记住它以及键本身和相关值。稍后执行查找时,哈希表会询问要查找的键以查找其哈希代码,并且可以非常快速地找到表中具有相同哈希代码的所有键

只要哈希表中的键在其整个生命周期中都保持相同的哈希代码,这一切都没问题。但是,如果它们是可变的,并且在插入哈希表后发生了变异,那么哈希代码通常会发生变化,在这一点上,当您搜索它时将永远找不到条目


当然,这只适用于影响平等的突变。例如,如果使用名称和生日对Person实体进行散列,但由于某种原因,仅使用名称表示相等,因此在计算散列码时仅使用名称,则可以将Person作为键插入哈希表,更改其生日,以后仍然可以毫无问题地再次查找它。

当您将一个键插入哈希表时,哈希表会询问该键的哈希代码,并记住它以及键本身和关联的值。稍后执行查找时,哈希表会询问要查找的键以查找其哈希代码,并且可以非常快速地找到表中具有相同哈希代码的所有键

只要哈希表中的键在其整个生命周期中都保持相同的哈希代码,这一切都没问题。但是,如果它们是可变的,并且在插入哈希表后发生了变异,那么哈希代码通常会发生变化,在这一点上,当您搜索它时将永远找不到条目


当然,这只适用于影响平等的突变。例如,如果使用名称和生日对Person实体进行散列,但由于某种原因,仅使用名称表示相等,因此在计算散列码时仅使用名称,则可以将Person作为键插入哈希表,更改其生日,以后仍然可以毫无问题地再次查找它。

字典类型是键和值之间的映射。映射将使用密钥的各种属性在内部字典存储中为其分配一个插槽。在大多数情况下,它将属性简化为int值


如果一个键随时间变化,那么它的属性可能会开始映射到表中的不同索引。因此,键将不再能够检索它最初在表中映射到的值。不可变类型完全避免了这种情况,因为它们永远不会改变。因此,它们的映射始终是一致的

字典类型是键和值之间的映射。映射将使用密钥的各种属性在内部字典存储中为其分配一个插槽。在大多数情况下,它将属性简化为int值


如果一个键随时间变化,那么它的属性可能会开始映射到表中的不同索引。因此,键将不再能够检索它最初在表中映射到的值。不可变类型完全避免了这种情况,因为它们永远不会改变。因此,它们的映射在任何时候都是一致的

字典根据密钥的哈希代码将项放置在存储桶中。如果您添加了一个项目,然后更改了它的键,您将无法再找到该项目


如果您使用新的键值来查找它,字典将在不同的存储桶中查找,如果您使用旧的键值,字典将找到它所在的存储桶,但键不再匹配。

字典将根据键的哈希代码将项目放入存储桶中。如果您添加了一个项目,然后更改了它的键,您将无法再找到该项目


如果您使用新的键值来查找它,字典将在另一个bucket中查找,如果您使用旧的键值,字典将找到它所在的bucket,但是键不再匹配。

请参阅我的答案,其中我详细描述了可变字典键的后果。字典是一种散列数据结构。如果您更改了一个键,但它仍然占据了数据结构中的同一个位置,散列是否会中断?是否使用了带有must for的确切问题标题?是否不应该回答您的问题或出现在搜索结果中?例如:在一个非常具体和复杂的要求中,我实现了一个IDictionary。我已经通过大量的测试场景对其进行了测试。XmlNodes已添加到和/或删除,但仍未中断。请参阅我在其中描述
字典是一种散列数据结构。如果您更改了一个键,但它仍然占据了数据结构中的同一个位置,散列是否会中断?是否使用了带有must for的确切问题标题?是否不应该回答您的问题或出现在搜索结果中?例如:在一个非常具体和复杂的要求中,我实现了一个IDictionary。我已经通过大量的测试场景对其进行了测试。XmlNodes已添加和/或删除,但仍没有中断。在什么情况下,它不会将密钥减少为int值?@AllonGuralnek如果字典实现为二进制搜索树。在这个实现中,你只需要知道相对顺序,它不一定必须是int,尽管在绝大多数情况下都是这样做的哦,你说的是一般意义上的,而我认为你说的是BCL中的实现。@AllonGuralnek正确。这个问题的原始版本没有指定语言/框架,因此我试图保持我的答案的概括性。在什么情况下,它不会将键减少为int值?@AllonGuralnek,如果字典被实现为二进制搜索树。在这个实现中,你只需要知道相对顺序,它不一定必须是int,尽管在绝大多数情况下都是这样做的哦,你说的是一般意义上的,而我认为你说的是BCL中的实现。@AllonGuralnek正确。这个问题的原始版本没有指定语言/框架,因此我试图保持我的答案的概括性。值得注意的是,由于问题中的XMLNode案例没有覆盖Equals或GetHashCode,它的相等概念基于标识,标识本身是不可变的。虽然这类对象很少用作键,但在确实有用的情况下,它们作为键是安全的。值得注意的是,由于问题中的XMLNode不覆盖Equals或GetHashCode,因此其相等概念基于标识,标识本身是不可变的。虽然这些对象很少用作键,但在确实有用的情况下,它们作为键是安全的。