General advice and guidelines on how to properly override object.GetHashCode()

前端 未结 11 1637
终归单人心
终归单人心 2020-12-01 00:09

According to MSDN, a hash function must have the following properties:

  1. If two objects compare as equal, the GetHashCode method for each object m

相关标签:
11条回答
  • 2020-12-01 00:40

    How to generate GetHashCode() and Equals()

    Visual Studio 2017
    https://docs.microsoft.com/en-us/visualstudio/ide/reference/generate-equals-gethashcode-methods?view=vs-2017

    ReSharper
    https://www.jetbrains.com/help/resharper/Code_Generation__Equality_Members.html

    0 讨论(0)
  • 2020-12-01 00:41

    How to make sure the hash code stays the same all through the object lifetime. (MSDN Property #2) Especially when the equality is based upon mutable fields. (MSDN Property #1)

    You seem to misunderstand Property #2. The hashcode doesn't need to stay the same thoughout the objects lifetime. It just needs to stay the same as long as the values that determine the outcome of the equals method are not changed. So logically, you base the hashcode on those values only. Then there shouldn't be a problem.

    0 讨论(0)
  • 2020-12-01 00:43

    What fields to base the hash code upon? If it should only be on immutable fields, what if there are only mutable ones?

    It doesn't need to be based only on immutable fields. I would base it on the fields that determine the outcome of the equals method.

    0 讨论(0)
  • 2020-12-01 00:48

    What are those magic numbers often seen in GetHashCode implementations?

    They are prime numbers. Prime numbers are used for creating hash codes because prime number maximize the usage of the hash code space.

    Specifically, start with the small prime number 3, and consider only the low-order nybbles of the results:

    • 3 * 1 = 3 = 3(mod 8) = 0011
    • 3 * 2 = 6 = 6(mod 8) = 1010
    • 3 * 3 = 9 = 1(mod 8) = 0001
    • 3 * 4 = 12 = 4(mod 8) = 1000
    • 3 * 5 = 15 = 7(mod 8) = 1111
    • 3 * 6 = 18 = 2(mod 8) = 0010
    • 3 * 7 = 21 = 5(mod 8) = 1001
    • 3 * 8 = 24 = 0(mod 8) = 0000
    • 3 * 9 = 27 = 3(mod 8) = 0011

    And we start over. But you'll notice that successive multiples of our prime generated every possible permutation of bits in our nybble before starting to repeat. We can get the same effect with any prime number and any number of bits, which makes prime numbers optimal for generating near-random hash codes. The reason we usually see larger primes instead of small primes like 3 in the example above is that, for greater numbers of bits in our hash code, the results obtained from using a small prime are not even pseudo-random - they're simply an increasing sequence until an overflow is encountered. For optimal randomness, a prime number that results in overflow for fairly small coefficients should be used, unless you can guarantee that your coefficients will not be small.

    Related links:

    • Why is ‘397’ used for ReSharper GetHashCode override?
    0 讨论(0)
  • 2020-12-01 00:52

    A) You must override both Equals and GetHashCode if you want to employ value equality instead of the default reference equality. With the later, two object references compare as equal if they both refer to the same object instance. With the former they compare as equal if their value is the same even if they refer to different objects. For example, you probably want to employ value equality for Date, Money, and Point objects.

    B) In order to implement value equality you must override Equals and GetHashCode. Both should depend on the fields of the object that encapsulate the value. For example, Date.Year, Date.Month and Date.Day; or Money.Currency and Money.Amount; or Point.X, Point.Y and Point.Z. You should also consider overriding operator ==, operator !=, operator <, and operator >.

    C) The hashcode doesn't have to stay constant all through the object lifetime. However it must remain immutable while it participates as the key in a hash. From MSDN doco for Dictionary: "As long as an object is used as a key in the Dictionary<(Of <(TKey, TValue>)>), it must not change in any way that affects its hash value." If you must change the value of a key remove the entry from the dictionary, change the key value, and replace the entry.

    D) IMO, you will simplify your life if your value objects are themselves immutable.

    0 讨论(0)
提交回复
热议问题