Един и същ GetHashCode() за различни обекти

След изпълнение на тази част от кода:

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.

Защо това се случва? Не трябва ли да връщат различни хешове?


person Matias Cicero    schedule 28.10.2014    source източник
comment
не е задължително - те са само ints.   -  person Daniel A. White    schedule 28.10.2014
comment
погледнете тук: referencesource.microsoft.com/#mscorlib/system / и referencesource.microsoft.com/#mscorlib/ система/   -  person Daniel A. White    schedule 28.10.2014
comment
Ако проверим равенството a.Equals(b), получаваме False, дори ако хешовете им са еднакви   -  person Matias Cicero    schedule 28.10.2014
comment
хешовете са един от начините за групиране на елементи заедно, а не за проверка на уникалността.   -  person Daniel A. White    schedule 28.10.2014
comment
Вашето погрешно схващане е, че различни или неравни обекти трябва да имат различни хеш кодове. Единственото изискване за хеш код е еднаквите обекти да имат еднакъв хеш код.   -  person juharr    schedule 28.10.2014


Отговори (4)


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.

person KugBuBu    schedule 28.10.2014
comment
Предполагам, че това обяснява всичко :) - person Matias Cicero; 28.10.2014

От документация на MSDN:

Два обекта, които са еднакви, връщат хеш кодове, които са еднакви. Обратното обаче не е вярно: еднаквите хеш кодове не предполагат равенство на обекти, тъй като различни (неравни) обекти могат да имат идентични хеш кодове.

person Icemanind    schedule 28.10.2014

Обекти, които са концептуално равни, са задължени да връщат едни и същи хешове. Обектите, които са различни, не са задължени да връщат различни хешове. Това би било възможно само ако има по-малко от 2^32 обекта, които някога биха могли да съществуват. Има повече от това. Когато обекти, които са различни, водят до един и същ хеш, това се нарича "сблъсък". Качественият хеш алгоритъм минимизира колизиите, доколкото е възможно, но те никога не могат да бъдат премахнати изцяло.

person Servy    schedule 28.10.2014
comment
Не знаех този факт! - person Matias Cicero; 28.10.2014
comment
Не трябва ли първото ви изречение да бъде Обекти, които са концептуално еднакви, са задължени да връщат същите хешове? - person juharr; 28.10.2014

Защо трябва? Хеш кодовете са краен набор; толкова, колкото можете да поберете в Int32. Има много много двойници, които ще имат същия хеш код като всеки даден int или всеки друг даден двоен код.

Хеш кодовете основно трябва да следват две прости правила:

  1. Ако два обекта са еднакви, те трябва да имат еднакъв хеш код.
  2. Ако даден обект не промени вътрешното си състояние, тогава хеш кодът трябва да остане същият.

Нищо не задължава два неравни обекта да имат различни хеш кодове; това е математически невъзможно.

person InBetween    schedule 28.10.2014