此GetHashCode方法中的位移值如何改善散列?

时间:2016-06-13 18:08:35

标签: c# hash bit-shift gethashcode

我在我正在研究的代码库中发现了两种带有哈希码方法的数据类型,我不完全理解它们被选中的原因:

public override int GetHashCode()
{
    return x.GetHashCode() ^ y.GetHashCode() << 2;
}

public override int GetHashCode()
{
    return x.GetHashCode() ^ y.GetHashCode() << 2 ^ z.GetHashCode() >> 2;
}

比特移位操作如何使这些哈希值更好?

1 个答案:

答案 0 :(得分:2)

假设您有一个由Pointx变量代表的y数据结构。如果没有位移,(1,0)的哈希码值将为1(0,1)的哈希码也将为1。现在对位移做同样的事情,对于(1,0),我们得到的散列码为1,但对于(0,1),我们现在得到的散列码为4

比特移位提供的是,如果您有相同的输入但是以不同的顺序想要获得不同的哈希码,那么(1,0)(0,1)最终不会落入相同的哈希桶并降低您的哈希集/字典性能。

通常情况下,你会做的偏差大于左移两次。如果处理Int32.MaxValue附近的哈希码,则Bitshifting还会导致数据被截断。这是我通常使用的模式

public override int GetHashCode()
{
    unchecked
    {
        var hashCode = X;
        hashCode = (hashCode*397) ^ Y;
        hashCode = (hashCode*397) ^ Z;
        return hashCode;
    }
}

(这是Resharper的“插入比较方法”功能附带的默认实现。要添加更多字段,您只需继续hashCode = (hashCode*397) ^ XXXXXXX

*unchecked而不是<<一起使用任何大于Int32.MaxValue的值只会溢出而不会出错。