我最近在struct
看到了这段代码,我想知道base.GetHashCode
实际上做了什么。
public override int GetHashCode()
{
var hashCode = -592410294;
hashCode = hashCode * -1521134295 + base.GetHashCode();
hashCode = hashCode * -1521134295 + m_Value.GetHashCode();
return hashCode;
}
答案 0 :(得分:7)
coreclr repo有this comment:
动作:我们返回哈希码的算法有点复杂。我们看 对于第一个非静态字段并获取它的哈希码。如果类型没有 非静态字段,我们返回该类型的哈希码。我们无法接受 静态成员的哈希码,因为如果该成员的类型与 原始类型,我们将以无限循环结束。
然而,代码并不存在,而且看起来并非相当会发生什么。样品:
using System;
struct Foo
{
public string x;
public string y;
}
class Test
{
static void Main()
{
Foo foo = new Foo();
foo.x = "x";
foo.y = "y";
Console.WriteLine(foo.GetHashCode());
Console.WriteLine("x".GetHashCode());
Console.WriteLine("y".GetHashCode());
}
}
我的盒子上的输出:
42119818
372029398
372029397
更改y
的值似乎不会更改foo
的哈希码。
但是,如果我们改为使用字段int
值,那么第一个字段会影响输出。
简而言之:这很复杂,您可能不应该依赖它在运行时的多个版本中保持不变。除非您真的非常确信您不需要将自定义结构用作基于哈希的字典/集中的键,否则我强烈建议覆盖GetHashCode
和{ {1}}(并实施Equals
以避免装箱)。
答案 1 :(得分:1)
结构的基类是ValueType
类,源代码在线。他们帮助留下了描述其工作原理的评论:
/*=================================GetHashCode==================================
**Action: Our algorithm for returning the hashcode is a little bit complex. We look
** for the first non-static field and get it's hashcode. If the type has no
** non-static fields, we return the hashcode of the type. We can't take the
** hashcode of a static member because if that member is of the same type as
** the original type, we'll end up in an infinite loop.
**Returns: The hashcode for the type.
**Arguments: None.
**Exceptions: None.
==============================================================================*/
[System.Security.SecuritySafeCritical] // auto-generated
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public extern override int GetHashCode();