После выполнения этой части кода:
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
. Оба obejcts возвращают один и тот же хэш-код: 0
.
Почему это происходит? Разве они не должны возвращать разные хеши?
GetHashCode
System.Int32
работает следующим образом:
public override int GetHashCode()
{
return this;
}
Который, конечно, с этим 0
, он вернет 0
.
System.Single
(float
- псевдоним) GetHashCode
:
public unsafe override int GetHashCode()
{
float num = this;
if (num == 0f)
{
return 0;
}
return *(int*)(&num);
}
Как вы видите, в 0f
он вернет 0
.
Используемая программа - ILSpy.
Два объекта, которые равны возвратным хеш-кодам, равным. Однако обратное неверно: равные хеш-коды не подразумевают равенства объектов, поскольку разные (неравные) объекты могут иметь одинаковые хэш-коды.
Объекты, которые концептуально равны, обязаны возвращать одни и те же хэши. Объекты, которые отличаются друг от друга, не обязаны возвращать разные хэши. Это было бы возможно только в том случае, если бы существовало менее 2 ^ 32 объектов, которые могли когда-либо существовать. Их больше. Когда объекты, которые отличаются друг от друга, приводят к одному и тому же хэшу, это называется "столкновением". Хэш-алгоритм качества минимизирует как можно больше конфликтов, но их невозможно полностью удалить.
Почему они должны? Хэш-коды - это конечный набор; столько, сколько вы можете поместиться в Int32
. Существует много много пар, которые будут иметь один и тот же хеш-код, как любой заданный int или любой другой двойной.
Хэш-коды в основном должны следовать двум простым правилам:
Ничто не обязывает два объекта, которые не равны другим хэш-кодам; это математически невозможно.