我最近在 struct
中看到这段代码,我想知道 base.GetHashCode
到底做了什么。
public override int GetHashCode()
{
var hashCode = -592410294;
hashCode = hashCode * -1521134295 + base.GetHashCode();
hashCode = hashCode * -1521134295 + m_Value.GetHashCode();
return hashCode;
}
coreclr 仓库有 this comment :
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.
但是,代码不在那里,看起来这不是完全发生的事情。示例:
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
values 而不是,那么第一个字段会影响输出。
简而言之:这很复杂,您可能不应该依赖它在运行时的多个版本中保持不变。除非您真的非常有信心不需要将自定义结构用作基于散列的字典/集合中的键,否则我强烈建议覆盖 GetHashCode
和 Equals
(并实现 IEquatable<T>
以避免装箱)。