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

前端 未结 11 1636
终归单人心
终归单人心 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:28

    Check out Guidelines and rules for GetHashCode by Eric Lippert

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

    Table of contents

    • When do I override object.GetHashCode?

    • Why do I have to override object.GetHashCode()?

    • What are those magic numbers seen in GetHashCode implementations?


    Things that I would like to be covered, but haven't been yet:

    • How to create the integer (How to "convert" an object into an int wasn't very obvious to me anyways).
    • What fields to base the hash code upon.
      • If it should only be on immutable fields, what if there are only mutable ones?
    • How to generate a good random distribution. (MSDN Property #3)
      • Part to this, seems to choose a good magic prime number (have seen 17, 23 and 397 been used), but how do you choose it, and what is it for exactly?
    • 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)
    • How to deal with fields that are complex types (not among the built-in C# types).
      • Complex objects and structs, arrays, collections, lists, dictionaries, generic types, etc.
      • For example, even though the list or dictionary might be readonly, that doesn't mean the contents of it are.
    • How to deal with inherited classes.
      • Should you somehow incorporate base.GetHashCode() into your hash code?
    • Could you technically just be lazy and return 0? Would heavily break MSDN guideline number #3, but would at least make sure #1 and #2 were always true :P
    • Common pitfalls and gotchas.
    0 讨论(0)
  • 2020-12-01 00:31
    public override int GetHashCode()
    {
        return IntProp1 ^ IntProp2 ^ StrProp3.GetHashCode() ^ StrProp4.GetHashCode ^ CustomClassProp.GetHashCode;
    }
    

    Do the same in the customClass's GetHasCode method. Works like a charm.

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

    When do I override object.GetHashCode()?

    As MSDN states:

    Types that override Equals must also override GetHashCode ; otherwise, Hashtable might not work correctly.

    Related links:

    • When to override GetHashCode()?
    0 讨论(0)
  • 2020-12-01 00:40

    Why do I have to override object.GetHashCode()?

    Overriding this method is important because the following property must always remain true:

    If two objects compare as equal, the GetHashCode method for each object must return the same value.

    The reason, as stated by JaredPar in a blog post on implementing equality, is that

    Many classes use the hash code to classify an object. In particular hash tables and dictionaries tend to place objects in buckets based on their hash code. When checking if an object is already in the hash table it will first look for it in a bucket. If two objects are equal but have different hash codes they may be put into different buckets and the dictionary would fail to lookup the object.

    Related links:

    • Do I HAVE to override GetHashCode and Equals in new Classes?
    • Do I need to override GetHashCode() on reference types?
    • Override Equals and GetHashCode Question
    • Why is it important to override GetHashCode when Equals method is overriden in C#?
    • Properly Implementing Equality in VB
    0 讨论(0)
  • 2020-12-01 00:40

    You should override it whenever you have a meaningful measure of equality for objects of that type (i.e. you override Equals). If you knew the object wasn't going to be hashed for any reason you could leave it, but it's unlikely you could know this in advance.

    The hash should be based only on the properties of the object that are used to define equality since two objects that are considered equal should have the same hash code. In general you would usually do something like:

    
    public override int GetHashCode()
    {
        int mc = //magic constant, usually some prime
        return mc * prop1.GetHashCode() * prop2.GetHashCode * ... * propN.GetHashCode();
    }
    

    I usually assume multiplying the values together will produce a fairly uniform distribution, assuming each property's hashcode function does the same, although this may well be wrong. Using this method, if the objects equality-defining properties change, then the hash code is also likely to change, which is acceptable given definition #2 in your question. It also deals with all types in a uniform way.

    You could return the same value for all instances, although this will make any algorithms that use hashing (such as dictionarys) very slow - essentially all instances will be hashed to the same bucket and lookup will then become O(n) instead of the expected O(1). This of course negates any benefits of using such structures for lookup.

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