GetHashCode计算

时间:2015-04-18 11:10:15

标签: c# gethashcode

我正在尝试覆盖GetHashCode以确保唯一性,因为我将实例用作字典中的键:

IDictionary<Base, int> _counts = new Dictionary<Base,int>();

我遇到的两个课程是:

class sealed First : Base
{
    public MyEnum1 value;
    public ExtrasEnum extras;

    public override int GetHashCode()
    {
        unchecked
        {
            return ((int)value* 397) ^ (int)extras;
        }   
    }

    //Other stuff
}

class sealed Second : Base
{
    public MyEnum2 value;
    public ExtrasEnum extras;

    public override int GetHashCode()
    {
        unchecked
        {
            return ((int)value* 397) ^ (int)extras;
        }            
    }

    //Other stuff
}

然而。问题是当valueextras int值相同时,哈希码将相等。 计算是Resharper的推荐计算。 我如何确保theese类的哈希码不一样? 只是将它与另一个素数混合起来,或者?

修改 只是解释一下。我需要,如果First的实例具有相同的valueextras值,则必须将这两个实例视为相同,但如果是First的实例,则Second的实例具有相同的valueextras的int值,因此不能将它们视为相同。

我不是在考虑性能,而只是为了确保相同的类实例是相同的,并且不同的类实例是不同的。

2 个答案:

答案 0 :(得分:3)

enum 成员生成完美哈希并不是很困难。假设他们不会超过256个成员,你可以写一个快速的成员:

public override int GetHashCode() {
    return ((int)value << 8) ^ (int)extras; 
}

通过将Second.GetHashCode()写为:

,根本不会产生任何冲突
public override int GetHashCode() {
    return ((int)value << 16) ^ (int)extras; 
}

非常简单和完美,但当您添加更多派生类时,当然不会扩展。它真的不需要,你是微观优化而没有任何洞察真正如何加速你的代码。请记住,完美的哈希不能避免字典中的桶冲突,桶索引是通过使用素数的哈希码的模来计算的。字典中的项目数越多,素数就越大。

根本就不要这样做。如果您想了解是否需要,请始终使用分析器。

答案 1 :(得分:2)

我认为您认为哈希码不得碰撞。一般来说,这显然是不可能确保的。 GetHashCode的以下实施始终有效:return 0;。 (这只是缓慢但不正确。)

这样做的方法是保持你的哈希码计算(因为它很好),但也要覆盖Equals。在那里你可以区分这两种类型。例如,说:

if (a.GetType() != b.GetType()) return false;

如果我误解了你的问题,你的问题的字面答案就是考虑到班级的类型:

oldHashCode ^ this.GetType().GetHashCode();

(这也不能确保唯一性。)