Почему реализация default == не вызывает Equals?
Возможный дубликат:
Почему оператор ReferenceEquals и == отличается от Equals
Стандартная реализация оператора ==
сравнивает объекты по ссылкам. Поэтому, когда вы переопределяете Equals (поведение по умолчанию такое же), вы также должны указывать операторы ==
и !=
, чтобы они вызывали Equals (и делали их в каждом классе иерархии как ==
и !=
) операторы не виртуальный).
Мой вопрос, почему это так? Почему ==
и !=
сравнивают объекты по ссылке вместо использования Equals? Наверное, должна быть причина для такой фундаментальной вещи.
Обновить.
К комментариям: Я предположил, что ==
должен зависеть от Equals (но не наоборот), поскольку вы можете переопределить Equals в базовом классе и автоматически использовать эту реализацию в производных классах. Он не будет работать, если Equals использовал ==
в своей реализации, поскольку ==
не является виртуальным.
Ответы
Ответ 1
Я считаю, что основной причиной является ==
- это статический оператор и может быть вызван на объекты null
, а Equals
требуется экземпляр.
Например:
Foo foo1 = null;
Foo foo2 = null;
Console.WriteLine(foo1 == foo2); // cannot use Equals
Ответ 2
Object.ReferenceEquals - это член static
, который сравнивает ссылочное равенство. Даже типы значений вставляются в бокс перед передачей этому методу.
Как насчет Equals
, это метод virtual
, что означает, что он позволяет потребителю переопределить функциональность.
Поэтому стандартная реализация поведения ==
предполагает, что сравнение по умолчанию (ссылка) подходит для вас, если вам нужно что-то конкретное, в этом случае среда предоставляет вам метод virtual
, который можно переопределить.
Ответ 3
"Причина" заключается в том, что иногда нужно знать, является ли A тем же экземпляром, что и B, в отличие от того, являются ли они просто "равными" друг другу.
Например, два объекта, равные друг другу, могут иметь смысл для большей части вашей бизнес-логики, однако вам также может понадобиться использовать некоторые утилиты concurrency, которые выполняют атомарные операции, в которых результаты зависят от идентичности объекта, а не равенство.
Ответ 4
==============================================================================================================================================================================================================
Просто потому, что С# не Objective C:)
Ответ 5
В Java иногда бывает полезно быстро определить, равны ли два идентификатора, просто сравнивая ссылки. ==
имеет место. Если вы посмотрите на генерируемый IDE метод equals
, вы часто обнаружите, что первое сделанное сравнение является ссылочным равенством, в конце концов, почему нужно проверять поля, если ссылки на объекты одинаковы?
Ответ 6
Я бы назвал это особенностью. По ссылке два идентичных объекта по-прежнему представляют собой два отдельных объекта. Если вы переопределите Equals, вы можете определить, идентичны ли два объекта. Даже если два объекта идентичны, я также могу проверить, являются ли те же объекты. У меня часто есть причина переопределить равные, но никогда не нужно переопределять ==!= (Но этот язык предоставляет эту опцию).
С строкой они переопределяют ==, и мне это не нравится. Хотя строка является ссылочным типом, операторы равенства (== и! =) Определены для сравнения значений строковых объектов, а не ссылок (7.9.7. Операторы равенства строк). Это делает тестирование для равенства строк более интуитивным. См. Проблему, которая была введена. WPF ListBox Прокрутите вниз