简体   繁体   English

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

[英]Creating 'good' hash codes for .NET ala Boost.Functional/Hash

For C++ I've always been using Boost.Functional/Hash to create good hash values without having to deal with bit shifts, XORs and prime numbers. 对于C ++,我一直在使用Boost.Functional / Hash创建好的哈希值,而不必处理位移,异或和素数。 Is there any libraries that produces good (I'm not asking for optimal) hash values for C#/.NET? 是否有任何库为C#/ .NET产生良好的(我不是要求最佳)哈希值? I would use this utility to implement GetHashCode(), not cryptographic hashes. 我会使用此实用程序来实现GetHashCode(),而不是加密哈希。

To clarify why I think this is useful, here's the implementation of boost::hash_combine which combines to hash values (ofcourse a very common operation when implementing GetHashCode()): 为了澄清我认为这有用的原因,这里是boost::hash_combine的实现,它结合了哈希值(当然是实现GetHashCode()时非常常见的操作):

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

Clearly, this sort of code doesn't belong in the implementation of GetHashCode() and should therefor be implemented elsewhere. 显然,这种代码不属于GetHashCode()的实现,因此应该在其他地方实现。

I wouldn't used a separate library just for that. 我不会仅仅为此使用单独的库。 As mentioned before, for the GetHashCode method it is essential to be fast and stable. 如前所述,对于GetHashCode方法,快速稳定至关重要。 Usually I prefer to write inline implementation, but it might be actually a good idea to use a helper class: 通常我更喜欢编写内联实现,但使用辅助类实际上可能是个好主意:

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;
        }
    }
}

This way common hash-calculation logic can be used: 这种方式可以使用常见的哈希计算逻辑:

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

Unless you have very specific requirements you don't need to calculate your type's hashcode from first principles. 除非您有非常具体的要求,否则您不需要从第一原则计算类型的哈希码。 Rather combine the hash codes of the fields/properties you use for equality determination in one of the simple ways, something like: 而是以一种简单的方式组合用于确定相等性的字段/属性的哈希码,例如:

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

(Combination function taken from §3.3.2 C# in Depth , 2 nd Ed, Jon Skeet ). (从§3.3.2采取组合函数C#中的深度第二版,乔恩斯基特 )。

The answers to this question contains some examples of helper-classes that resembles Boost.Functional/Hash. 这个问题的答案包含一些类似于Boost.Functional / Hash的辅助类的例子。 None looks quite as elegant, though. 但是,没有一个看起来更优雅。

I am not aware of any real .NET library that provides the equivalent. 我不知道任何真正的.NET库提供等效的。

To avoid the boxing issue chain your calls using a generic extension method on Int32 为了避免装箱问题,请使用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();
        }
    }

}

then you can do 那么你可以做到

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

Have a look at this link , it describes MD5 hashing. 看看这个链接 ,它描述了MD5哈希。 Otherwise use GetHashCode(). 否则使用GetHashCode()。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM