As GökhanKurt explained in the comments, the number changes based upon the property names involved. If you rename the property to Halue
, the number becomes 387336856 instead. I had tried it with different classes but didn't think of renaming the property.
Gökhan's comment made me understand its purpose. It's offsetting hash values based on a deterministic, but randomly distributed offset. This way, combining hash values for different classes, even with a simple addition, is still slightly resistant to hash collisions.
For instance, if you have two classes with a similar GetHashCode implementations:
public class A
{
public int Value { get; set;}
public int GetHashCode() => Value;
}
public class B
{
public int Value { get; set;}
public override int GetHashCode() => Value;
}
and if you have another class that contains references to these two:
public class C
{
public A ValueA { get; set; }
public B ValueB { get; set; }
public override int GetHashCode()
{
return ValueA.GetHashCode() + ValueB.GetHashCode();
}
}
a poor combination like this would be prone to hash collisions because the resulting hash code would accumulate around the same area for different values of ValueA and ValueB if their values are close to each other. It really doesn't matter if you use multiplication or bitwise operations to combine them, they would still be prone to collisions without an evenly distanced offset. As many integer values used in programming are accumulated around 0, it makes sense to use such an offset
Apparently, it's a good practice to have a random offset with good bit patterns.
I'm still not sure why they don't use completely random offsets, probably not to break any code that relies on determinism of GetHashCode(), but it would be great to receive a comment from Visual Studio team about this.