Подтвердить что ты не робот

Несогласованность методов Equals и GetHashCode

После прочтения этого вопроса Почему "int" и "sbyte" Функции GetHashCode генерируют разные значения? Я хотел копать дальше и нашел следующее поведение:

sbyte i = 1;            
int j = 1;
object.Equals(i, j) //false (1)
object.Equals(j, i) //false (2) 
i.Equals(j) //false (3)
j.Equals(i) //true (4)
i == j //true (5)
j == i //true (6)
i.GetHashCode() == j.GetHashCode() //false (7)
  • Разница между (3) и (4) нарушает требование о симметричности Equals.
  • Разница между (2) и (4) не согласуется с спецификацией MSDN, которая гласит:

    Если два объекта не представляют одну и ту же ссылку на объект и none равно null, он вызывает objA.Equals(objB) и возвращает результат. Это означает, что если objA переопределяет метод Object.Equals(Object) это переопределение вызывается.

  • Разница между (3) и (5) означает, что оператор == возвращает true, однако объекты не равны в терминах Equals.
  • Разница между (4), (5), (6) и (7) означает, что два объекта равны в терминах оператора == и Equals, однако они имеют разные хэш-коды.

Мне очень интересно, может ли кто-нибудь объяснить, почему такое, по моему мнению, противоречивое поведение наблюдается в довольно фундаментальных типах .NET.

4b9b3361

Ответ 1

Ваша проблема в том, что вы пропустили неявное преобразование в i.Equals(j). Это перегрузка int.Equals(int). Здесь вы сравниваете i и (int)j, которые являются одним и тем же. Такое же неявное преобразование происходит для ==.

Другие сравнения работают с int и a sbyte, которые по определению различны. j.Equals(i) переходит к перегрузке int.Equals(object), потому что аргумент неявно конвертируется в sbyte.

Equals является симметричным для них, но ваш код вызова не является. Если вы подавите неявное преобразование с помощью i.Equals((object)j), оно вернет false, показывая, что Equals действительно симметрично.