Вопрос

Каков наилучший способ создать свой собственный метод GetHashCode для класса в C #?Предположим, у меня есть простой класс (который переопределяет метод Equals), следующим образом:

class Test
{
   public string[] names;

   public double[] values;

   public override bool Equals(object obj)
   {
      return (obj is Test) && this.Equals((Test)obj);
   }

   public bool Equals(Test t)
   {
      return names.Equals(t.names) && values.Equals(t.values);
   }
}

Должен ли я использовать код по умолчанию для метода GetHashCode?

public override int GetHashCode()
{
   return base.GetHashCode();
}

Должен ли я основывать метод на содержимом моего класса?

public override int GetHashCode()
{
   return names.GetHashCode() + values.GetHashCode() ;
}

Или я должен сделать что-то еще?

Это было полезно?

Решение

System.Array не переопределяет GetHashCode или Equals, поэтому они используют ссылочное равенство.Следовательно, вам не следует им звонить.

Для реализации GetHashCode, видеть этот вопрос.

Для реализации Equals, используйте SequenceEqual метод расширения.

Редактировать:В .Net 2.0 вам придется написать свою собственную версию SequenceEqual, вот так:

public static bool SequenceEquals<T>(IList<T> first, IList<T> second) {
    if (first == second) return true;
    if (first == null || second == null) return false;

    if (first.Count != second.Count) return false;

    for (int i = 0; i < first.Count; i++)
        if (!first[i].Equals(second[i]))
            return false;

    return true;
}

Вы могли бы написать это, чтобы взять IEnumerable<T> вместо того , чтобы IList<T>, но это было бы несколько медленнее, потому что он не смог бы завершить работу раньше, если параметры имеют разные размеры.

Другие советы

Действительно важно убедиться, что вы сохраняете переопределение .GetHashCode() в шаге с помощью .Равно().

В принципе, вы должны убедиться, что они рассматривают одни и те же поля, чтобы не нарушать первое из трех правил GetHashCode (из Объект MSDN.Получить хэш-код())

Если два объекта сравниваются как равные, то Метод GetHashCode для каждого объекта должен возвращать одно и то же значение.Однако, если два объекта не сравниваются как равные, методы GetHashCode для двух объектов не должны возвращать разные значения.

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

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

Есть хорошее обсуждение этих вопросов здесь, и самое последнее обновление относится к Абстрактный класс BaseObject предоставлено SharpArchitecture.

Если ты хочешь чего-то большего ad hoc, Я обнаружил, что код, который ReSharper генерирует для Equals() и GetHashCode(), в порядке.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top