如何成功地哈希System.Windows.Input。带修改器的键值?

时间:2021-09-16 21:09:55

I am trying to write a hashing algorithm that's gonna successfully hash System.Windows.Input.Key values with modifier key states, for instance:

我在写一个散列算法它可以成功地散列System.Windows.Input。带有修饰符键状态的键值,例如:

ctrl = false
shift = true
alt = false
capslock = true
numlock = false
scroll lock = false
key: A

So a key value like this should be separated from others with different states for ctrl, shift, alt, etc. But since these are just true or false, I am not sure how to make it distinct for the hash values?

因此,像这样的键值应该与其他键值分离,并使用不同的状态进行ctrl、shift、alt等操作。但是由于这些键值都是真或假的,所以我不知道如何区分哈希值?

Any ideas? It just have to be unique enough to handle all possible key combinations.

什么好主意吗?它必须有足够的独特性来处理所有可能的关键组合。

1 个解决方案

#1


1  

I would build a class containing all values able to compute it's own hash code, like:

我将构建一个包含所有值的类,这些值可以计算它自己的哈希代码,比如:

    class KeyInfo : IEquatable<KeyInfo>
    {
        public bool Ctrl { get; private set; }
        public bool Shift { get; private set; }
        public bool Alt { get; private set; }
        public bool CapsLock { get; private set; }
        public bool NumLock { get; private set; }
        public bool ScrollLock { get; private set; }
        public Keys Key { get; private set; }

        public KeyInfo(bool ctrl, bool shift, bool alt, bool capsLock, bool numLock, bool scrollLock, Keys key)
        {
            this.Ctrl = ctrl;
            this.Shift = shift;
            this.Alt = alt;
            this.CapsLock = capsLock;
            this.NumLock = numLock;
            this.ScrollLock = scrollLock;
            this.Key = key;
        }

        public override bool Equals(object obj)
        {
            return this.Equals(obj as KeyInfo);
        }

        public bool Equals(KeyInfo other)
        {
            if (other == null)
                return false;
            return this.Ctrl == other.Ctrl && this.Shift == other.Shift &&
                   this.Alt == other.Alt && this.CapsLock == other.CapsLock &&
                   this.NumLock == other.NumLock && this.ScrollLock == other.ScrollLock &&
                   this.Key == other.Key;
        }

        public override int GetHashCode()
        {
            unchecked
            {
                int hash = 17;
                hash = hash * 23 + this.Ctrl.GetHashCode();
                hash = hash * 23 + this.Shift.GetHashCode();
                hash = hash * 23 + this.Alt.GetHashCode();
                hash = hash * 23 + this.CapsLock.GetHashCode();
                hash = hash * 23 + this.NumLock.GetHashCode();
                hash = hash * 23 + this.ScrollLock.GetHashCode();
                hash = hash * 23 + this.Key.GetHashCode();
                return hash;
            }
        }
    }

Credits to this Jon Skeet's answer for the GetHashCode() implementation.

感谢Jon Skeet对GetHashCode()实现的回答。

N.B.

注意:

this class can be effectively used as a Dictionary key, into HashSet or in LINQ Distinct() and other LINQ sets' operations.

这个类可以有效地用作字典键、哈希集或LINQ Distinct()和其他LINQ集的操作。

EDIT:

编辑:

I'd like to enforce the fact that you mustn't use the hash code as dictionary key, but use the whole class instead.
You cannot rely on the uniqueness of the hash-codes because hashing it's subjected to collisions.

我想强调的是,您不应该使用哈希代码作为字典键,而是使用整个类。您不能依赖哈希码的惟一性,因为哈希码会受到碰撞。

#1


1  

I would build a class containing all values able to compute it's own hash code, like:

我将构建一个包含所有值的类,这些值可以计算它自己的哈希代码,比如:

    class KeyInfo : IEquatable<KeyInfo>
    {
        public bool Ctrl { get; private set; }
        public bool Shift { get; private set; }
        public bool Alt { get; private set; }
        public bool CapsLock { get; private set; }
        public bool NumLock { get; private set; }
        public bool ScrollLock { get; private set; }
        public Keys Key { get; private set; }

        public KeyInfo(bool ctrl, bool shift, bool alt, bool capsLock, bool numLock, bool scrollLock, Keys key)
        {
            this.Ctrl = ctrl;
            this.Shift = shift;
            this.Alt = alt;
            this.CapsLock = capsLock;
            this.NumLock = numLock;
            this.ScrollLock = scrollLock;
            this.Key = key;
        }

        public override bool Equals(object obj)
        {
            return this.Equals(obj as KeyInfo);
        }

        public bool Equals(KeyInfo other)
        {
            if (other == null)
                return false;
            return this.Ctrl == other.Ctrl && this.Shift == other.Shift &&
                   this.Alt == other.Alt && this.CapsLock == other.CapsLock &&
                   this.NumLock == other.NumLock && this.ScrollLock == other.ScrollLock &&
                   this.Key == other.Key;
        }

        public override int GetHashCode()
        {
            unchecked
            {
                int hash = 17;
                hash = hash * 23 + this.Ctrl.GetHashCode();
                hash = hash * 23 + this.Shift.GetHashCode();
                hash = hash * 23 + this.Alt.GetHashCode();
                hash = hash * 23 + this.CapsLock.GetHashCode();
                hash = hash * 23 + this.NumLock.GetHashCode();
                hash = hash * 23 + this.ScrollLock.GetHashCode();
                hash = hash * 23 + this.Key.GetHashCode();
                return hash;
            }
        }
    }

Credits to this Jon Skeet's answer for the GetHashCode() implementation.

感谢Jon Skeet对GetHashCode()实现的回答。

N.B.

注意:

this class can be effectively used as a Dictionary key, into HashSet or in LINQ Distinct() and other LINQ sets' operations.

这个类可以有效地用作字典键、哈希集或LINQ Distinct()和其他LINQ集的操作。

EDIT:

编辑:

I'd like to enforce the fact that you mustn't use the hash code as dictionary key, but use the whole class instead.
You cannot rely on the uniqueness of the hash-codes because hashing it's subjected to collisions.

我想强调的是,您不应该使用哈希代码作为字典键,而是使用整个类。您不能依赖哈希码的惟一性,因为哈希码会受到碰撞。