Для любого числа с плавающей запятой Equals
и ==
ведут себя по-разному.
NaN==NaN => false
в соответствии с логикой IEEE
NaN.Equals(NaN) => true
Выполнение требования, что все должно быть равным себе.
И, конечно, Equals
переопределяется, т. Е. Работает даже тогда, когда статический тип является базовым типом, тогда как ==
перегружен и работает, только если статический тип был перегружен.
Я почти никогда не звоню x.Equals(y)
напрямую. С одной стороны, он не обрабатывает x
, являясь null
, и его асимметрия - это отвратительная ИМО. Статический object.Equals(x,y)
вызывает виртуальный метод object.Equals(y)
, но добавляет обработку нуля.
IEquatable<T>.Equals(other)
эквивалентно object.Equals(other)
для всех типов с хорошим поведением, но позволяет избежать упаковки в типы значений.
В заключение я обычно предпочитаю ==
, когда известен статический тип, и EqualityComparer<T>.Default
с универсальными типами или, если статический тип не соответствует типу времени выполнения.
В вашем примере Name
и Id
ведут себя одинаково с ==
и Equals
, поскольку string
и int
запечатаны.
TheObject
, с другой стороны, демонстрирует различное поведение с ==
и Equals
для определенных типов. Например, если вы используете string
, тогда Equals
будет использовать равенство значений, а ==
будет использовать равенство ссылок.