Подтвердить что ты не робот

Как использовать HashSet <T> в качестве словарного ключа?

Я хочу использовать HashSet<T> как ключ к словарю:

Dictionary<HashSet<T>, TValue> myDictionary = new Dictionary<HashSet<T>, TValue>();

Я хочу искать значения из словаря, так что два разных экземпляра HashSet<T>, которые содержат одни и те же элементы, возвращают одинаковое значение.

HashSet<T> реализация Equals() и GetHashCode(), похоже, не делает этого (я думаю, что они просто значения по умолчанию). Я могу переопределить Equals() для использования SetEquals(), но как насчет GetHashCode()? Я чувствую, что здесь что-то не хватает...

4b9b3361

Ответ 1

Вы можете использовать установленный компаратор, предоставленный HashSet<T>:

var myDictionary = new Dictionary<HashSet<T>, TValue>(HashSet<T>.CreateSetComparer());

Ответ 2

digEmAll ответ, безусловно, лучший выбор на практике, поскольку он использует встроенный код вместо того, чтобы изобретать колесо. Но я оставлю это как примерную реализацию.


Вы можете использовать реализацию IEqualityComparer<HashSet<T>>, которая использует SetEquals. Затем передайте его конструктору Словаря. Что-то вроде следующего (не проверял):

class HashSetEqualityComparer<T>: IEqualityComparer<HashSet<T>>
{
    public int GetHashCode(HashSet<T> hashSet)
    {
        if(hashSet == null)
           return 0;
        int h = 0x14345843; //some arbitrary number
        foreach(T elem in hashSet)
        {
            h = unchecked(h + hashSet.Comparer.GetHashCode(elem));
        }
        return h;
    }

    public bool Equals(HashSet<T> set1, HashSet<T> set2)
    {
        if(set1 == set2)
            return true;
        if(set1 == null || set2 == null)
            return false;
        return set1.SetEquals(set2);
    }
}

Обратите внимание, что хеш-функция здесь коммутативна, что важно, потому что порядок перечисления элементов в наборе undefined.

Еще один интересный момент заключается в том, что вы не можете просто использовать elem.GetHashCode, поскольку это даст неправильные результаты, когда пользовательский сопоставитель сравнений был поставлен в набор.

Ответ 3

Вы можете предоставить IEqualityComparer<HashSet<T>> конструктору словаря и внести желаемую реализацию в этот компаратор.