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.