Как переопределить GetHashCode со списками в объекте - PullRequest
0 голосов
/ 17 ноября 2009

Я пытаюсь создать KeySet для изменения поведения UIElement. Идея состоит в том, чтобы создать специальную функцию, если, например. пользователь нажимает на элемент, удерживая. Или 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);
        }
    }

Ответы [ 2 ]

0 голосов
/ 18 ноября 2009

Чтобы ответить на мой собственный (слегка сложный) вопрос, вот решение:

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;
    }
}
0 голосов
/ 17 ноября 2009
 _testDict.Add(new KeyModifierSet(Key.A), () => Debug.WriteLine("nothing"));
 if (!_testDict.ContainsKey(new KeyModifierSet(Key.A))) throw new Exception("Not done yet, help :-)");

Если я правильно понимаю ваш код, вы хотели бы протестировать ваш объект _testDict Dictionary на равенство, используя переопределенные версии методов Object.Equals и Object.GetHashCode. Насколько я знаю, вам нужно будет создать свой собственный тип коллекции, который переопределяет эти методы.

...