Ответ
Метод GetHashCode() возвращает 32-битное целое число (int), которое представляет хеш-код объекта. Это значение используется в качестве ключа в хеш-таблицах, таких как Dictionary<TKey, TValue> и HashSet<T>, для быстрого определения местоположения объекта и сравнения.
Ключевые контракты метода:
- Консистентность: Для одного и того же объекта, состояние которого не изменилось, метод должен возвращать одно и то же значение в течение всего времени жизни приложения.
- Согласованность с Equals: Если два объекта равны согласно методу
Equals(object), то их хеш-коды, возвращаемыеGetHashCode(), должны быть одинаковыми. - Коллизии допускаются: Обратное утверждение неверно. Разные объекты (для которых
Equalsвозвращаетfalse) могут иметь одинаковый хеш-код (коллизия). Однако хорошая реализация стремится минимизировать коллизии для производительности.
Пример использования:
string str1 = "hello";
string str2 = "hello";
string str3 = "world";
Console.WriteLine(str1.GetHashCode() == str2.GetHashCode()); // True: одинаковые строки
Console.WriteLine(str1.GetHashCode() == str3.GetHashCode()); // False (с высокой вероятностью): разные строки
Важные замечания:
- Для ссылочных типов по умолчанию
GetHashCode()возвращает значение, основанное на идентификаторе потока и внутреннем индексе объекта в управляемой куче. Это не является адресом в памяти, но уникально для объекта в рамках процесса. - Для изменяемых (mutable) типов переопределять
GetHashCode()крайне не рекомендуется. Если объект, используемый как ключ в словаре, изменяется после добавления, его хеш-код может измениться, и объект станет недоступен для поиска, что приведет к ошибкам. -
При переопределении
Equals(object)обязательно переопределяйте иGetHashCode(), чтобы соблюсти контракт. Хорошая реализация использует те же поля, что иEquals.public class Person { public int Id { get; init; } public string Name { get; init; } public override bool Equals(object obj) => obj is Person p && Id == p.Id && Name == p.Name; public override int GetHashCode() => HashCode.Combine(Id, Name); // Используем встроенный комбинатор }