Один и тот же GetHashCode() для разных объектов

#c# #system.type

#c# #.net #хэш-код

Вопрос:

После выполнения этого фрагмента кода:

 int a = 50;
float b = 50.0f;
Console.WriteLine(a.GetHashCode() == b.GetHashCode());
  

Мы получаем False , что и ожидалось, поскольку мы имеем дело с разными объектами, следовательно, мы должны получить разные хэши.

Однако, если мы выполним это:

 int a = 0;
float b = 0.0f;
Console.WriteLine(a.GetHashCode() == b.GetHashCode());
  

Получаем True . Оба объекта возвращают один и тот же хэш-код: 0 .

Почему это происходит? Разве они не должны возвращать разные хэши?

Комментарии:

1. не нессаралы — это всего лишь целые числа.

2. взгляните сюда: referencesource.microsoft.com/#mscorlib/system /… и referencesource.microsoft.com/#mscorlib/system /…

3. Если мы проверим равенство a.Equals(b) , мы получим False , даже если их хэши одинаковы

4. хэши — это один из способов сгруппировать элементы вместе, а не проверять уникальность.

5. Ваше заблуждение заключается в том, что разные или неравные объекты должны иметь разные хэш-коды. Единственное требование к хэш-коду заключается в том, чтобы равные объекты имели одинаковый хэш-код.

Ответ №1:

GetHashCode Of System.Int32 работает следующим образом:

 public override int GetHashCode()
{
    return this;
}
  

Что, конечно, при таком значении 0 , он вернет 0 .

System.Single ‘s ( float — псевдоним) GetHashCode является:

 public unsafe override int GetHashCode()
{
    float num = this;
    if (num == 0f)
    {
        return 0;
    }
    return *(int*)(amp;num);
}
  

Как вы видите, в 0f он вернется 0 .

Используемая программа — ILSpy.

Комментарии:

1. Я думаю, это все объясняет 🙂

Ответ №2:

Из документации MSDN:

Два одинаковых объекта возвращают одинаковые хэш-коды. Однако обратное неверно: равные хэш-коды не подразумевают равенства объектов, поскольку разные (неравные) объекты могут иметь идентичные хэш-коды.

Ответ №3:

Объекты, которые концептуально равны, обязаны возвращать одинаковые хэши. Разные объекты не обязаны возвращать разные хэши. Это было бы возможно только в том случае, если бы существовало менее 2 ^ 32 объектов, которые когда-либо могли существовать. Их больше. Когда разные объекты приводят к одному и тому же хэшу, это называется «столкновением». Качественный алгоритм хэширования максимально минимизирует коллизии, но они никогда не могут быть удалены полностью.

Комментарии:

1. Не знал этого факта!

2. Разве ваше первое предложение не должно быть «Объекты, которые концептуально равны, обязаны возвращать одинаковые хэши»?

Ответ №4:

Почему они должны? Хэш-коды — это конечный набор; столько, сколько вы можете вместить в Int32 . Существует много-много двойников, которые будут иметь тот же хэш-код, что и любой заданный int или любой другой заданный double.

Хэш-коды в основном должны следовать двум простым правилам:

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

Ничто не обязывает два объекта, которые не равны, иметь разные хэш-коды; это математически невозможно.