I saw this code recently in a struct
and I was wondering what base.GetHashCode
actually does.
public override int GetHashCode()
{
var hashCode = -592410294;
hashCode = hashCode * -1521134295 + base.GetHashCode();
hashCode = hashCode * -1521134295 + m_Value.GetHashCode();
return hashCode;
}
The coreclr repo has 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.
However, the code isn't there, and it looks like that's not quite what happens. Sample:
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());
}
}
Output on my box:
42119818
372029398
372029397
Changing the value of y
doesn't appear to change the hash code of foo
.
However, if we make the fields int
values instead, then more than the first field affects the output.
In short: this is complex, and you probably shouldn't depend on it remaining the same across multiple versions of the runtime. Unless you're really, really confident that you don't need to use your custom struct as a key in a hash-based dictionary/set, I'd strongly recommend overriding GetHashCode
and Equals
(and implementing IEquatable<T>
to avoid boxing).
See more on this question at Stackoverflow