Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I usually go with something like the implementation given in Josh Bloch's <em>fabulous</em> <a href="https://rads.stackoverflow.com/amzn/click/0321356683" rel="noreferrer">Effective Java</a>. It's fast and creates a pretty good hash which is unlikely to cause collisions. Pick two different prime numbers, e.g. 17 and 23, and do:</p> <pre><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; } } </code></pre> <p>As noted in comments, you may find it's better to pick a large prime to multiply by instead. Apparently 486187739 is good... and although most examples I've seen with small numbers tend to use primes, there are at least similar algorithms where non-prime numbers are often used. In the not-quite-<a href="https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function" rel="noreferrer">FNV</a> example later, for example, I've used numbers which apparently work well - but the initial value isn't a prime. (The multiplication constant <em>is</em> prime though. I don't know quite how important that is.)</p> <p>This is better than the common practice of <code>XOR</code>ing hashcodes for two main reasons. Suppose we have a type with two <code>int</code> fields:</p> <pre><code>XorHash(x, x) == XorHash(y, y) == 0 for all x, y XorHash(x, y) == XorHash(y, x) for all x, y </code></pre> <p>By the way, the earlier algorithm is the one currently used by the C# compiler for anonymous types.</p> <p><a href="http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx" rel="noreferrer">This page</a> gives quite a few options. I think for most cases the above is "good enough" and it's incredibly easy to remember and get right. The <a href="http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx#fnv" rel="noreferrer">FNV</a> alternative is similarly simple, but uses different constants and <code>XOR</code> instead of <code>ADD</code> as a combining operation. It looks <em>something</em> like the code below, but the normal FNV algorithm operates on individual bytes, so this would require modifying to perform one iteration per byte, instead of per 32-bit hash value. FNV is also designed for variable lengths of data, whereas the way we're using it here is always for the same number of field values. Comments on this answer suggest that the code here doesn't actually work as well (in the sample case tested) as the addition approach above.</p> <pre><code>// Note: Not quite FNV! public override int GetHashCode() { unchecked // Overflow is fine, just wrap { int hash = (int) 2166136261; // Suitable nullity checks etc, of course :) hash = (hash * 16777619) ^ field1.GetHashCode(); hash = (hash * 16777619) ^ field2.GetHashCode(); hash = (hash * 16777619) ^ field3.GetHashCode(); return hash; } } </code></pre> <p>Note that one thing to be aware of is that ideally you should prevent your equality-sensitive (and thus hashcode-sensitive) state from changing after adding it to a collection that depends on the hash code.</p> <p>As per the <a href="http://msdn.microsoft.com/en-us/library/system.object.gethashcode%28v=vs.110%29.aspx" rel="noreferrer">documentation</a>:</p> <blockquote> <p>You can override GetHashCode for immutable reference types. In general, for mutable reference types, you should override GetHashCode only if:</p> <ul> <li>You can compute the hash code from fields that are not mutable; or</li> <li>You can ensure that the hash code of a mutable object does not change while the object is contained in a collection that relies on its hash code.</li> </ul> </blockquote>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload