One if the ways to implement GetHashCode - where it's required to do so - is outlined by Jon Skeet here. Repeating his code:
public override int GetHashCode()
{
unchecked // Overflow is fine, just wrap
{
int hash = 17;
// Suitable nullity checks etc, of course :)
hash = hash * 23 + field1.GetHashCode();
hash = hash * 23 + field2.GetHashCode();
hash = hash * 23 + field3.GetHashCode();
return hash;
}
}
Rolling this code by hand can be error-prone and bugs can be subtle/hard to spot (did you swap +
and *
by mistake?), it can be hard to remember the combination rules for different types, and I don't like expending mental effort on writing/reviewing the same thing over and over again for different fields and classes. It can also obfuscate one of the most important details (did I remember to include all the fields?) in repetitive noise.
Is there a concise way to combine field hashcodes using the .net library?. Obviously I could write my own, but if there's something idiomatic/built-in I'd prefer that.
As an example, in Java (using JDK7) I can achieve the above using:
@Override
public int hashCode()
{
return Objects.hash(field1, field2, field3);
}
This really helps to eliminate bugs and focus in the important details.
Motivation: I came across a C# class which requires an overridden GetHashCode()
, but the way it combined the hashcodes of its various constituents had some severe bugs. A library function for combining the hashcodes would be useful for avoiding such bugs.
Some people use:
It's mentioned on MSDN at
Object.GetHashCode()
, with the warning:The logic of aggregating the constituent hashes is provided by
System.Tuple
, which hopefully has had some thought go into it...Update: it is worth noting @Ryan's observation in the comments that this only appears to use the last 8 elements of any Tuple of Size>8.
Here are a couple of concise (though not as efficient) refactors of the
System.Web.Util.HashCodeCombiner
mentioned in Ryan's answerEDIT: Stay tuned, System.HashCode is coming to .NET Core, and will provide a singular best-practice way to create hashcodes. It will also be used under the hood by System.Tuple and other immutable composite types. Until it is released, the answer below is still useful.
For the sake of completeness, here is the hashing algorithm taken from the .NET Tuple Reference source, line 52. Interestingly, this hash algorithm was copied over from
System.Web.Util.HashCodeCombiner
.Here is the code:
Of course, the actual Tuple
GetHashCode()
(which is actually anInt32 IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
) has a largeswitch
block to decide which one of these to call based upon how many items it is holding - your own code probably won't require that.It's not exactly the same, but we have a
HashCodeHelper
class in Noda Time (which has lots of types which override equality and hash code operations).It's used like this (taken from
ZonedDateTime
):Note that it's a generic method, which avoids boxing for value types. It copes with null values automatically (using 0 for the value). Note that the
MakeHash
method has anunchecked
block as Noda Time uses checked arithmetic as a project setting, whereas hash code calculations should be allowed to overflow.