为.NET ala Boost.Functional / Hash创建“好”哈希码

时间:2011-06-21 09:03:45

标签: c# .net hash

对于C ++,我一直在使用Boost.Functional/Hash创建好的哈希值,而不必处理位移,异或和素数。是否有任何库为C#/ .NET产生良好的(我不是要求最佳)哈希值?我会使用此实用程序来实现GetHashCode(),而不是加密哈希。

为了澄清为什么我认为这是有用的,这里是boost::hash_combine的实现,它结合了哈希值(当然是实现GetHashCode()时非常常见的操作):

seed ^= hash_value(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);

显然,这类代码不属于GetHashCode()的实现,因此应该在其他地方实现。

5 个答案:

答案 0 :(得分:4)

我不会仅仅为此使用单独的库。如前所述,对于GetHashCode方法,快速稳定至关重要。通常我更喜欢编写内联实现,但实际上使用辅助类可能是个好主意:

internal static class HashHelper
{
    private static int InitialHash = 17; // Prime number
    private static int Multiplier = 23; // Different prime number

    public static Int32 GetHashCode(params object[] values)
    {
        unchecked // overflow is fine
        {
            int hash = InitialHash;

            if (values != null)
                for (int i = 0; i < values.Length; i++)
                {
                    object currentValue = values[i];
                    hash = hash * Multiplier
                        + (currentValue != null ? currentValue.GetHashCode() : 0);
                }

            return hash;
        }
    }
}

这种方式可以使用常见的哈希计算逻辑:

public override int GetHashCode()
{
    return HashHelper.GetHashCode(field1, field2);
}

答案 1 :(得分:1)

除非您有非常具体的要求,否则您不需要从第一原则计算类型的哈希码。而是以一种简单的方式组合用于确定相等性的字段/属性的哈希码,例如:

int hash = field1.GetHashCode();
hash = (hash *37) + field2.GetHashCode();

(组合函数取自§3.3.2C# in Depth, 2nd Ed, Jon Skeet)。

答案 2 :(得分:1)

this question的答案包含一些类似于Boost.Functional / Hash的辅助类的示例。但是,没有一个看起来很优雅。

我不知道有任何真正的.NET库提供等效的。

答案 3 :(得分:0)

要避免装箱问题,请使用Int32上的通用扩展方法链接您的调用

public static class HashHelper
{
    public static int InitialHash = 17; // Prime number
    private static int Multiplier = 23; // Different prime number

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static Int32 GetHashCode<T>( this Int32 source, T next )
    {
        // comparing null of value objects is ok. See
        // http://stackoverflow.com/questions/1972262/c-sharp-okay-with-comparing-value-types-to-null
        if ( next == null )
        {
            return source;
        }
        unchecked
        {
            return source + next.GetHashCode();
        }
    }

}

然后你可以做

HashHelper
    .InitialHash
    .GetHashCode(field0)
    .GetHashCode(field1)
    .GetHashCode(field2);

答案 4 :(得分:-3)

看一下这个link,它描述了MD5哈希。 否则使用GetHashCode()。