Самым важным свойством, которое должна иметь реализация хэш-кода, является следующее:
Если два объекта сравниваются как равные, то они должны иметь одинаковые хэш-коды.
Если у вас есть класс, в котором экземпляры сравнения классов по ссылочному равенству, то вам не нужно переопределять GetHashCode; реализация по умолчанию гарантирует, что два объекта, которые являются одной и той же ссылкой, имеют одинаковый хэш-код. (Вы вызываете один и тот же метод дважды для одного и того же объекта, поэтому, конечно, результат будет одинаковым.)
Если вы написали класс, который реализует собственное равенство, которое отличается от ссылочного равенства, то вам ТРЕБУЕТСЯ переопределить GetHashCode, чтобы два объекта, которые сравниваются как равные, имели одинаковые хэш-коды.
Теперь вы можете сделать это, просто возвращая каждый раз ноль. Это была бы паршивая хеш-функция, но это было бы законно.
Другие свойства хороших хэш-функций:
GetHashCode никогда не должен генерировать исключение.
Изменяемые объекты, которые сравниваются на равенство в своем изменяемом состоянии, и, следовательно, хэш в своем изменяемом состоянии, опасно подвержены ошибкам. Вы можете поместить объект в хеш-таблицу, изменить его и больше не получить. Старайтесь никогда не хешировать и не сравнивать на равенство изменяемых состояний.
GetHashCode должен быть очень быстрым - помните, цель хорошего алгоритма хеширования - повысить производительность поиска. Если хеширование выполняется медленно, поиск не может выполняться быстро.
Объекты, которые не сравниваются как равные, должны иметь разные хеш-коды, хорошо распределенные по всему диапазону 32-битного целого числа
Вопрос:
Это правда? Мне кажется, что у двух объектов не будет одного и того же хэш-кода, потому что код объекта не используется повторно до тех пор, пока объект не будет собран (т.е. перестанет существовать).
Два объекта могут использовать один и тот же хэш-код, если он сгенерирован по умолчанию реализацией GetHashCode, потому что:
Заключение: Достаточно выделить 2 ^ 32 объекта с сильными ссылками (должно быть легко в Win64), чтобы достичь предела.
Наконец, в объекте есть явное выражение. Ссылка GetHashCode в MSDN : реализация метода GetHashCode по умолчанию не гарантирует уникальных возвращаемых значений для различных объектов. Кроме того, .NET Framework не гарантирует реализацию метода GetHashCode по умолчанию, и значение, которое он возвращает, будет одинаковым для разных версий .NET Framework. Следовательно, реализация этого метода по умолчанию не должна использоваться в качестве уникального идентификатора объекта для целей хеширования.
На самом деле вам не нужно ничего изменять в классе, для которого требуется только ссылка равенство.
Кроме того, формально это не очень хорошая реализация, поскольку она плохо распространение. Хеш-функция должна иметь разумное распределение, поскольку она улучшает распределение хэш-корзин и, косвенно, производительность в коллекциях, в которых используются хеш-таблицы. Как я уже сказал, это формальный ответ, одно из руководящих принципов при разработке хеш-функции.