11

Possible Duplicate:
What is the best algorithm for an overridden System.Object.GetHashCode?

I need to override GetHashCode method for a type which consists of three strings. Here is my code:

protected override int GetHashCode()
{
    return str1.GetHashCode() + str2.GetHashCode() + str3.GetHashCode();
}

What is a safe way of this method implementation?

Community
  • 1
  • 1
SiberianGuy
  • 24,674
  • 56
  • 152
  • 266

2 Answers2

19

The best way is to avoid anything that would produce the same hash code if you:

  • swapped the order of the operands
  • has a mostly-zero value and just move the non-zero value around

Both addition (by itself) and XOR fails on these accounts.

Here's a better approach:

public override int GetHashCode()
{
    unchecked
    {
        int result = 37; // prime

        result *= 397; // also prime (see note)
        if (str1 != null)
            result += str1.GetHashCode();

        result *= 397;
        if (str2 != null)
            result += str2.GetHashCode();

        result *= 397;
        if (str2 != null)
            result += str2.GetHashCode();

        return result;
    }
}

Whether you use addition or XOR inside that code is up for debate, I've seen examples using both with no clear analysis of which is superior (ie. uniform distribution). Pick one and go with it.

397 is the default value used by the ReSharper addin when it generates GetHashCode implementations, and is apparently selected because it typically overflows the range of the int and thus mixes bits a bit better. There are many theories around this particular format of GetHashCode implementation, but it's the most used one.

Community
  • 1
  • 1
Lasse V. Karlsen
  • 380,855
  • 102
  • 628
  • 825
4

I always use exclusive or (Xor) rather than addition, because it doesn't have a tendency to get numbers anywhere (like toward large values). So I would say that

protected override int GetHashCode()
{ return str1.GetHashCode() ^ str2.GetHashCode() ^ str3.GetHashCode(); }

is a better implementation.

You could also try a variation on it, like

protected override int GetHashCode()
{
    unchecked
    {
        return (str1.GetHashCode() * 1369) ^
               (str2.GetHashCode() * 37) ^ str3.GetHashCode();
    }
}

if you want to make sure that switching the values of the strings gives a different result. There's all sorts of methods that can be used for hashing (e.g. universal hashing) so just do a search for hashing methods if that's what you're looking for.

user541686
  • 205,094
  • 128
  • 528
  • 886