C# - 如何使用对象中的列表覆盖 GetHashCode

发布于 2024-08-11 17:04:14 字数 2016 浏览 5 评论 0原文

我正在尝试创建一个“KeySet”来修改 UIElement 行为。这个想法是创建一个特殊的函数,例如:用户按住 a 的同时单击一个元素。或者ctrl+a。

到目前为止,我的方法是,首先让我们为所有可能的修饰符创建一个容器。如果我只允许使用单个密钥,那就没问题了。我可以使用一个简单的字典,

Dictionary<Keys, Action> _specialActionList
  • 如果字典为空,则使用默认操作。
  • 如果有条目,请根据当前按下的键检查要使用的操作

如果我不贪心,那就是...... 当然,现在我想要更多。我想允许多个键或修饰符。因此,我创建了一个包装类,它可以用作我的字典的键。

使用更复杂的类时存在一个明显的问题。目前两个不同的实例会创建两个不同的密钥,因此他永远不会找到我的函数(请参阅代码来理解,非常明显)

现在我检查了这篇文章: GetHashCode 覆盖包含通用数组的对象 这有一点帮助。

但我的问题是,我的课程基本设计可以吗?我应该使用哈希集来存储修饰符和普通键盘键(而不是列表)。如果是这样,GetHashCode 函数会是什么样子?

我知道,需要编写大量代码(无聊的哈希函数),一些提示足以让我开始。将在这里发布试用...

到目前为止的代码,测试显然失败了...

        public class KeyModifierSet
    {
        private readonly List<Key> _keys = new List<Key>();
        private readonly List<ModifierKeys> _modifierKeys = new List<ModifierKeys>();

        private static readonly Dictionary<KeyModifierSet, Action> _testDict 
                          = new Dictionary<KeyModifierSet, Action>();

        public static void Test()
        {
            _testDict.Add(new KeyModifierSet(Key.A), () => Debug.WriteLine("nothing"));
            if (!_testDict.ContainsKey(new KeyModifierSet(Key.A))) throw new Exception("Not done yet, help :-)");
        }

        public KeyModifierSet(IEnumerable<Key> keys, IEnumerable<ModifierKeys> modifierKeys)
        {
            foreach (var key in keys)
                _keys.Add(key);

            foreach (var key in modifierKeys)
                _modifierKeys.Add(key);
        }

        public KeyModifierSet(Key key, ModifierKeys modifierKey)
        {
            _keys.Add(key);
            _modifierKeys.Add(modifierKey);
        }

        public KeyModifierSet(Key key)
        {
            _keys.Add(key);
        }
    }

I am trying to create a "KeySet" to modify UIElement behaviour. The idea is to create a special function if, eg. the user clicks on an element while holding a. Or ctrl+a.

My approach so far, first lets create a container for all possible modifiers. If I would simply allow a single key, it would be no problem. I could use a simple Dictionary, with

Dictionary<Keys, Action> _specialActionList
  • If the dictionary is empty, use the default action.
  • If there are entries, check what action to use depending on current pressed keys

And if I wasn't greedy, that would be it...
Now of course, I want more. I want to allow multiple keys or modifiers. So I created a wrapper class, wich can be used as Key to my dictionary.

There is an obvious problem when using a more complex class. Currently two different instances would create two different key, and thereby he would never find my function (see code to understand, really obvious)

Now I checked this post: GetHashCode override of object containing generic array which helped a little.

But my question is, is my basic design for the class ok. Should I use a hashset to store the modifier and normal keyboardkeys (instead of Lists). And If so, how would the GetHashCode function look like?

I know, its a lot of code to write (boring hash functions), some tips would be sufficient to get me started. Will post tryouts here...

And here comes the code so far, the Test obviously fails...

        public class KeyModifierSet
    {
        private readonly List<Key> _keys = new List<Key>();
        private readonly List<ModifierKeys> _modifierKeys = new List<ModifierKeys>();

        private static readonly Dictionary<KeyModifierSet, Action> _testDict 
                          = new Dictionary<KeyModifierSet, Action>();

        public static void Test()
        {
            _testDict.Add(new KeyModifierSet(Key.A), () => Debug.WriteLine("nothing"));
            if (!_testDict.ContainsKey(new KeyModifierSet(Key.A))) throw new Exception("Not done yet, help :-)");
        }

        public KeyModifierSet(IEnumerable<Key> keys, IEnumerable<ModifierKeys> modifierKeys)
        {
            foreach (var key in keys)
                _keys.Add(key);

            foreach (var key in modifierKeys)
                _modifierKeys.Add(key);
        }

        public KeyModifierSet(Key key, ModifierKeys modifierKey)
        {
            _keys.Add(key);
            _modifierKeys.Add(modifierKey);
        }

        public KeyModifierSet(Key key)
        {
            _keys.Add(key);
        }
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

小猫一只 2024-08-18 17:04:14
 _testDict.Add(new KeyModifierSet(Key.A), () => Debug.WriteLine("nothing"));
 if (!_testDict.ContainsKey(new KeyModifierSet(Key.A))) throw new Exception("Not done yet, help :-)");

如果我正确理解您的代码,您希望使用 Object.Equals 和 Object.GetHashCode 方法的重写版本来测试 _testDict Dictionary 对象的相等性。据我所知,您将需要创建自己的自定义集合类型来覆盖这些方法。

 _testDict.Add(new KeyModifierSet(Key.A), () => Debug.WriteLine("nothing"));
 if (!_testDict.ContainsKey(new KeyModifierSet(Key.A))) throw new Exception("Not done yet, help :-)");

If I understand your code correctly you would like to test your _testDict Dictionary object for equality using overrided versions of the Object.Equals and Object.GetHashCode methods. As far as I know you will need to create your own custom collection type that overrides these methods.

愛放△進行李 2024-08-18 17:04:14

为了回答我自己的(提出的稍微复杂的)问题,解决方案如下:

public class KeyModifierSet
{
    internal readonly HashSet<Key> Keys = new HashSet<Key>();
    internal readonly HashSet<ModifierKeys> MKeys = new HashSet<ModifierKeys>();

    public override int GetHashCode()
    {
        int hash = Keys.Count + MKeys.Count;
        foreach (var t in Keys)
        {
            hash *= 17;
            hash = hash + t.GetHashCode();
        }
        foreach (var t in MKeys)
        {
            hash *= 19;
            hash = hash + t.GetHashCode();
        }
        return hash;
    }

    public override bool Equals(object obj)
    {
        return Equals(obj as KeyModifierSet);
    }
    public bool Equals(KeyModifierSet other)
    {
        // Check for null
        if (ReferenceEquals(other, null))
            return false;

        // Check for same reference
        if (ReferenceEquals(this, other))
            return true;

        // Check for same Id and same Values
        return Keys.SetEquals(other.Keys) && MKeys.SetEquals(other.MKeys);
    }



    public KeyModifierSet(ModifierKeys mKey)
    {
        MKeys.Add(mKey);
    }
    public KeyModifierSet(Key key)
    {
        Keys.Add(key);
    }
    public KeyModifierSet(Key key, ModifierKeys mKey)
    {
        Keys.Add(key);
        MKeys.Add(mKey);
    }
    public KeyModifierSet Add(Key key)
    {
        Keys.Add(key);
        return this;
    }
    public KeyModifierSet Add(ModifierKeys key)
    {
        MKeys.Add(key);
        return this;
    }
}

To answer my own (slightly complicated posed) question, here is the solution:

public class KeyModifierSet
{
    internal readonly HashSet<Key> Keys = new HashSet<Key>();
    internal readonly HashSet<ModifierKeys> MKeys = new HashSet<ModifierKeys>();

    public override int GetHashCode()
    {
        int hash = Keys.Count + MKeys.Count;
        foreach (var t in Keys)
        {
            hash *= 17;
            hash = hash + t.GetHashCode();
        }
        foreach (var t in MKeys)
        {
            hash *= 19;
            hash = hash + t.GetHashCode();
        }
        return hash;
    }

    public override bool Equals(object obj)
    {
        return Equals(obj as KeyModifierSet);
    }
    public bool Equals(KeyModifierSet other)
    {
        // Check for null
        if (ReferenceEquals(other, null))
            return false;

        // Check for same reference
        if (ReferenceEquals(this, other))
            return true;

        // Check for same Id and same Values
        return Keys.SetEquals(other.Keys) && MKeys.SetEquals(other.MKeys);
    }



    public KeyModifierSet(ModifierKeys mKey)
    {
        MKeys.Add(mKey);
    }
    public KeyModifierSet(Key key)
    {
        Keys.Add(key);
    }
    public KeyModifierSet(Key key, ModifierKeys mKey)
    {
        Keys.Add(key);
        MKeys.Add(mKey);
    }
    public KeyModifierSet Add(Key key)
    {
        Keys.Add(key);
        return this;
    }
    public KeyModifierSet Add(ModifierKeys key)
    {
        MKeys.Add(key);
        return this;
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文