是字典损坏或应GetHash上永恒不变的会员code()只有基地?永恒不变、字典、基地、会员

2023-09-05 00:00:29 作者:自作多情的思念,那叫犯賤

当一个对象被添加到.NET System.Collections.Generic.Dictionary类的密钥的散列code为内部存储并用于以后的比较。当它的初始插入到它往往成为不可访问,并可能惊讶它的用户时存在确认,即使使用相同的附图,返回false(样品$ C $以下c)该辞典后的散列code的变化。

借助 GetHash code 的文件说:

  

在GetHash code方法的对象必须一致地返回相同的散列code,只要没有修改对象的状态,确定对象的equals方法的返回值。

因此​​,根据 GetHash code 文档,散列code可以随时更改的平等 - 确定状态发生变化,但在词典的实施做不支持的。

是当前.NET字典实现破的,因为它错误地忽视了哈希code津贴?如果 GetHash code()只能根据永恒不变的成员?或者,有没有别的东西,打破了可能的错误的二分法?

 类哈希
{
    公众诠释PK {获得;组; }

    公众覆盖INT GetHash code()
    {
        如果(PK!= 0)返回PK.GetHash code();
        返回base.GetHash code();
    }

    公众覆盖布尔等于(obj对象)
    {
        回报等于(OBJ作为哈希);
    }

    公共虚拟布尔等于(哈希等)
    {
        如果(其他== NULL)返回false;
        否则,如果(的ReferenceEquals(这一点,其他))返回true;
        否则,如果(PK = 0&放大器;!&安培; other.PK!= 0)返回等于(PK,other.PK);
        返回false;
    }

    公共重写字符串的ToString()
    {
        返回的String.Format(哈希{0},PK);
    }
}

类测试
{
    静态无效的主要(字串[] args)
    {
        VAR字典=新字典<哈希,布尔>();
        VAR H =新的哈希();
        dict.Add(h时,真正的);

        h.PK = 42;
        如果(!dict.ContainsKey(H))//返回false,尽管相同的参考
            dict.Add(H,FALSE);
    }
}
 

解决方案 Python学习笔记 字典 dict

没有,你只是不应该发生变异,将其插入到字典后,一键(在材料的方式)。这是由设计,并且每个哈希表我用过的工作方式。该文档还具体说明这一点:

  

只要一个对象被用作词典℃的密钥; TKEY的,TValue> ,它不能在任何影响其散列值的方式变化。 TKEY的,TValue>在词典和其中每一个关键必须按照字典的相等比较器是唯一的。键不能为空,但一个值就可以了,如果值类型TValue为引用类型。

所以,它一定会大吃一惊谁不读文档的用户:)

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).

The GetHashCode documentation says:

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.

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

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:

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 :)