How to implement GetHashCode() in a C# struct [duplicate]
Asked Answered
S

1

0

I have a struct that overrides the Equals() method and the compiler complains about GetHashCode() not being overridden.

My struct:

  private struct Key
  {
    ...

    public override int GetHashCode()
    {
      return ?;
    }

    public int FolderID;
    public MyEnum SubItemKind;
    public int SubItemID;
  }

What is the right way to implement the GetHashCode() method?

a)

    return FolderID ^ SubItemKind.GetHashCode() ^ SubItemID;

or b)

    return FolderID.GetHashCode() ^ SubItemKind.GetHashCode() ^ SubItemID.GetHashCode();
Seagraves answered 10/9, 2015 at 12:40 Comment(2)
System.Int32.GetHashCode() performs a simple return this (at least in mscorlib v4), so your two code snippets would be equivalent anyway.Floorwalker
This question is not specific to struct. The core of the problem is combining multiple hash codes into one, which is explained in the top answer to the "What is the best algorithm for an overridden System.Object.GetHashCode?" question.Phocaea
G
3

Always the latter. The former isn't sufficient because most bits are 0 (your numbers are most likely small), and those zeroes are in the most significant bits. You'd be wasting a lot of the hash code, thus getting a lot more collisions.

Another common way of doing it is to multiply each item by a prime number and relying on overflows:

return unchecked(FolderID.GetHashCode() * 23 * 23 
                 + SubItemKind.GetHashCode() * 23 
                 + SubItemID.GetHashCode());

Edit: Updated to use unchecked for explicit overflow support as per stakx's comment.

Gudrin answered 10/9, 2015 at 12:45 Comment(4)
Don't forget to wrap the whole expression in an unchecked(…) block, otherwise you might get an exception due to possible arithmetic overflows.Issiah
See also this answer by Jon Skeet to the question, "What is the best algorithm for an overridden System.Object.GetHashCode?".Issiah
Didn't know he commented on the subject, yeah unchecked makes sense.Gudrin
I hope you don't mind the code edit. You don't need a unchecked { … } block. You can use the variant for just one in-line expression (unchecked (…), i.e. with parentheses).Issiah

© 2022 - 2024 — McMap. All rights reserved.