Мне просто пришлось добавить еще один ответ, потому что не было упомянуто одно из наиболее очевидных (и самых простых в реализации) решений - не включать коллекцию в ваш расчет GetHashCode
!
Главное, что тут как будто забыли, это то, что уникальность от результата GetHashCode
не требуется (а во многих случаях даже возможна). Неравные объекты не должны возвращать неравные хэш-коды, единственное требование состоит в том, чтобы одинаковые объекты возвращали одинаковые хэш-коды. Таким образом, по этому определению следующая реализация GetHashCode
верна для всех объектов (при условии, что существует правильная реализация Equals
):
public override int GetHashCode()
{
return 42;
}
Конечно, это приведет к наихудшей возможной производительности при поиске по хеш-таблице, O(n) вместо O(1), но функционально это все еще корректно.
Имея это в виду, моя общая рекомендация при реализации GetHashCode
для объекта, который имеет какую-либо коллекцию в качестве одного или нескольких своих членов, состоит в том, чтобы просто игнорировать их и вычислять GetHashCode
исключительно на основе других скалярных членов. Это будет работать довольно хорошо, если только вы не поместите в хеш-таблицу огромное количество объектов, все их скалярные члены имеют одинаковые значения, что приведет к идентичным хэш-кодам.
Игнорирование членов коллекции при вычислении хэш-кода также может привести к повышению производительности, несмотря на уменьшение распределения значений хэш-кода. Помните, что использование хеш-кода должно улучшить производительность в хеш-таблице, поскольку не требует вызова Equals
N раз, а вместо этого требует только один раз вызова GetHashCode и быстрого поиска в хеш-таблице. Если каждый объект имеет внутренний массив с 10 000 элементов, каждый из которых участвует в вычислении хеш-кода, все преимущества, полученные от хорошего распределения, вероятно, будут потеряны. Было бы лучше иметь немного менее распространенный хеш-код, если его создание обходится значительно дешевле.
person
Allon Guralnek
schedule
21.08.2012