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