Краткий ответ: я думаю, что ваше второе предположение может быть ошибочным. Equals()
- это правильный способ проверки семантического равенства двух объектов, а не operator ==
.
<Ч />
Длинный ответ: Разрешение перегрузки для операторов выполняется во время компиляции, а не во время выполнения .
Если компилятор не может точно знать типы объектов, к которым применяется оператор, он не будет компилироваться. Поскольку компилятор не может быть уверен, что IAddress
будет чем-то, что имеет переопределение для ==
, он возвращается к реализации operator ==
по умолчанию System.Object
.
Чтобы увидеть это более четко, попробуйте определить operator +
для Address
и добавить два IAddress
экземпляра. Если вы явно не приведете к Address
, компиляция не удастся. Зачем? Поскольку компилятор не может сказать, что конкретный IAddress
является Address
, и не существует реализации по умолчанию operator +
, к которой можно обратиться в System.Object
.
<Ч />
Частично ваше разочарование, вероятно, связано с тем, что Object
реализует operator ==
, а все - Object
, поэтому компилятор может успешно разрешать такие операции, как a == b
для всех типов. Когда вы переопределили ==
, вы ожидали увидеть то же поведение, но не увидели, и это потому, что лучшее соответствие, которое может найти компилятор, - это оригинальная реализация Object
.
Требование всех сравнений использовать Equals вместо оператора == не является жизнеспособным решением, особенно при передаче ваших типов в библиотеки (такие как Коллекции).
На мой взгляд, это именно то, что вы должны делать. Equals()
- это правильный способ проверки семантического равенства двух объектов. Иногда семантическое равенство - это просто ссылочное равенство, и в этом случае вам не нужно ничего менять. В других случаях, как в вашем примере, вы переопределите Equals
, когда вам нужен более сильный контракт равенства, чем ссылочное равенство. Например, вы можете считать, что два Persons
равны, если у них одинаковый номер социального страхования, или два Vehicles
равны, если у них одинаковый VIN.
Но Equals()
и operator ==
- это не одно и то же. Всякий раз, когда вам нужно переопределить operator ==
, вы должны переопределить Equals()
, но почти никогда наоборот. operator ==
больше синтаксического удобства. Некоторые языки CLR (например, Visual Basic.NET) даже не позволяют переопределить оператор равенства.