GetHashCode для элементов словаря - PullRequest
0 голосов
/ 30 июля 2011

Я переопределяю метод Equals для одного из моих классов.В этом методе я проверяю равенство каждой пары словаря и пары словаря другого экземпляра, как это делает следующий код:

    public override bool Equals (object obj)
    {
        ...
        // compare to make sure all <key, value> pair of this.dict have
        // the match in obj.dict

        ...
    }

Теперь мне нужно переопределить метод GetHashCode, а также то, чтопредложил.

Нужно ли это делать для всех ключей словаря или ключей плюс значения?

По существу, следующее будет хорошим или излишним?

public override int GetHashCode ()
{
    int iHash = 0;

    foreach (KeyValuePair<string, T> pair in this.dict)
    {
        iHash ^= pair.Key.GetHashCode();
        iHash ^= pair.Value.GetHashCode();
    }

    return iHash;
}

Ответы [ 2 ]

1 голос
/ 30 июля 2011

Учитывая то, с чем связан @Mitch Wheat, это не лучший способ сделать GetHashCode (), если вы используете этот класс со словарем или HashSet.

Представьте, что ваш внутренний словарь содержит только одну запись. Ваш хэш теперь является значением этого единственного KeyValuePair. Вы вставляете весь класс в HashSet. Вы добавляете еще один элемент к вашему внутреннему Dictionary. Теперь хэш-код вашего класса изменился, потому что вы перебираете два элемента в своем классе.

Когда вы вызываете HashSet.Contains(obj), он вызывает obj.GetHashCode(), который теперь изменился, даже если это тот же экземпляр класса. HashSet.Contains() обнаружит, что он не содержит этот новый хеш, и вернет false, никогда не вызывая Equals (который вернет true, если ссылки совпадают).

Внезапно, как будто ваш объект исчез из HashSet, даже если класс находится там, с устаревшим хешем.

Вы действительно не хотите, чтобы ваш хэш изменился. В вашей GetHashCode нормально иметь коллизии, потому что, если она сталкивается, она вызовет (более медленный) метод .Equals(). Это удобная оптимизация, которая, если она неправильно реализована, может вызвать некоторые головные боли на этом пути.

В качестве примечания, как указано в ссылке выше, неплохо бы умножить ваш хэш на простое число до ^ с другим значением. Помогает с сохранением уникальности.

0 голосов
/ 30 июля 2011

Планируете ли вы использовать объект в HashSet?Вам действительно нужно реализовать GetHashCode только в том случае, если объект будет использоваться таким образом, что он требует, чтобы он был уникально идентифицирован по хешу. является хорошей практикой - всегда реализовывать GetHashCode с учетом тех же полей, которые используются в равенстве, но не всегда необходимо.

Если это необходимо в вашем случае, я полагаю, что у вас естьправильная идея.

...