字典是破坏还是应该GetHashCode()只是基于不可变的成员? [英] Is Dictionary broken or should GetHashCode() only base on immutable members?

查看:107
本文介绍了字典是破坏还是应该GetHashCode()只是基于不可变的成员?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

将对象添加到.NET System.Collections.Generic.Dictionary 类的密钥的哈希码在内部存储并用于以后的比较。当哈希码在初始插入字典之后变化时,通常会变得不可访问,并且即使使用相同的引用返回false(存在下面的示例代码),存在检查也可能使用户感到惊讶。

When an object is added to the .NET System.Collections.Generic.Dictionary class the hashcode of the key is stored internally and used for later comparisons. When the hashcode changes after its initial insertion into the dictionary it often becomes "inaccessible" and may surprise its users when an existence check, even using the same reference, returns false (sample code below).

GetHashCode 文档说:


只要对确定返回的对象状态没有修改,对象的GetHashCode方法必须始终返回相同的哈希码对象的Equals方法的值。

The GetHashCode method for an object must consistently return the same hash code as long as there is no modification to the object state that determines the return value of the object's Equals method.

所以,根据 GetHashCode ,每当等级时,哈希码可能会更改 - 确定状态已更改,但字典实现不支持此操作。

So, according to the GetHashCode docs, the hashcode may change whenever equality-determining state is changed, yet the Dictionary implementation does not support this.

是当前的.NET字典实现因为它错误地忽略了哈希码容许金,因此被打破了?应该 GetHashCode()只能基于不可变的成员?或者,还有其他的东西可以打破可能的假二分法吗?

Is the current .NET dictionary implementation broken in that it incorrectly ignore the hashcode allowances? Should GetHashCode() only be based on immutable members? Or, is there something else to break a possible false dichotomy?

class Hashable
{
    public int PK { get; set; }

    public override int GetHashCode()
    {
        if (PK != 0) return PK.GetHashCode();
        return base.GetHashCode();
    }

    public override bool Equals(object obj)
    {
        return Equals(obj as Hashable);
    }

    public virtual bool Equals(Hashable other)
    {
        if (other == null) return false;
        else if (ReferenceEquals(this, other)) return true;
        else if (PK != 0 && other.PK != 0) return Equals(PK, other.PK);
        return false;
    }

    public override string ToString()
    {
        return string.Format("Hashable {0}", PK);
    }
}

class Test
{
    static void Main(string[] args)
    {
        var dict = new Dictionary<Hashable, bool>();
        var h = new Hashable();
        dict.Add(h, true);

        h.PK = 42;
        if (!dict.ContainsKey(h)) // returns false, despite same reference
            dict.Add(h, false);
    }
}


推荐答案

否在插入字典后,您不应该将键(以实质的方式)变异。这是通过设计,以及我使用过的每个哈希表的工作原理。文档甚至指定了这一点:

No, you just shouldn't mutate a key (in a material way) after inserting it into a dictionary. This is by design, and the way that every hash table I've ever used works. The docs even specify this:


只要一个对象用作 Dictionary< TKey中的一个键, TValue> ,它不得以影响其哈希值的任何方式进行更改。根据字典的等式比较器, Dictionary< TKey,TValue> 中的每个键都必须是唯一的。键不能为空,但如果值类型为TValue为参考类型,则值为。

As long as an object is used as a key in the Dictionary<TKey, TValue>, it must not change in any way that affects its hash value. Every key in a Dictionary<TKey, TValue> must be unique according to the dictionary's equality comparer. A key cannot be null, but a value can be, if the value type TValue is a reference type.

惊喜的用户谁不阅读文件:)

So it's only going to surprise users who don't read documentation :)

这篇关于字典是破坏还是应该GetHashCode()只是基于不可变的成员?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆