0

Currently, I have the following two enum types:

[Flags]
public enum KeyboardLocks :
    byte
{
    None       = 0,
    NumLock    = 1 << 0,
    CapsLock   = 1 << 1,
    ScrollLock = 1 << 2
}

[Flags]
public enum KeyboardModifiers :
    byte
{
    None         = 0,
    LeftAlt      = 1 << 0,
    LeftControl  = 1 << 1,
    LeftShift    = 1 << 2,
    RightAlt     = 1 << 3,
    RightControl = 1 << 4,
    RightShift   = 1 << 5
}

These are both wrapped into a single state object, which represents the state of the modifier keys on the keyboard:

public struct ModifierState
{
    // (Constructor and get-only properties omitted)    
    public readonly KeyboardLocks Locks;
    public readonly KeyboardModifiers Modifiers;

    public override int GetHashCode()
    {
        int hash = 19;
        hash = (hash * 257) + Locks.GetHashCode();
        hash = (hash * 257) + Modifiers.GetHashCode();
        return hash;
    }
}

After doing a little bit of research, I found out that GetHashCode() will simply return the value for byte and int. I've looked at other questions, and it seems that the best approach is to pick two primes that don't overlap with the internal hash table.

I noticed that if I went with 17 and 23, as suggested, values would regularly collide (at least according to a spreadsheet I made). I used 19 and 257 instead, because it would assign each enum a unique value.

Am I missing the point here? I very rarely make types that need to override GetHashCode(), so I have no idea if this is remotely correct.

Community
  • 1
  • 1
Kyle Baran
  • 1,793
  • 2
  • 15
  • 30
  • 1
    "How can I tell if my GetHashCode() function is suitable?" Suitable for what? – Sriram Sakthivel May 17 '15 at 17:34
  • Suitable... for being used as a hash function? As written, it won't produce duplicate values. Is that desireable? – Kyle Baran May 17 '15 at 17:35
  • 2
    It is suitable. You can make it faster with return Locks.GetHashCode() + Modifiers.GetHashCode() << 4; – Hans Passant May 17 '15 at 17:39
  • `GetHashCode` isn't a method for generating uniqueness of an object. A good hash code method should be randomly distributed – Yuval Itzchakov May 17 '15 at 17:39
  • 2
    Any hashcode which collides minimally, executes fast, returns consistent value is a good implementation. IIRC resharpers suggests 397 as the prime to implement hashcode. You don't need to guarantee uniqueness (you can't). All you will desire is minimal collision. – Sriram Sakthivel May 17 '15 at 17:39
  • Does it matter? The hashcode is mainly used for dictionary lookups where hash % bucketsize gives you the bucket number which contains the list of values with the same hash code. The list count is the number of hash collisions in your dictionary. This will slow down lookup and insert operations. As long as you do not have perf problems there you are optimizing at the wrong spot of your application. – Alois Kraus May 17 '15 at 21:39
  • According to the class design guidelines, if == is overridden (which it is), then !=, GetHashCode, and Equals should also be overridden; I want to make sure I implemented these properly. – Kyle Baran May 18 '15 at 08:08

0 Answers0