Компилятор С# требует, чтобы всякий раз, когда пользовательский тип определяет оператор ==
, он также должен определить !=
(см. здесь).
Почему?
Мне любопытно узнать, почему дизайнеры считают это необходимым и почему компилятор не может использовать разумную реализацию для любого из операторов, когда присутствует только другой. Например, Lua позволяет вам определить только оператор равенства, а другой - бесплатно. С# мог бы сделать то же самое, попросив вас определить либо == или оба == и! =, А затем автоматически скомпилировать отсутствующий оператор = = как !(left == right)
.
Я понимаю, что есть странные угловые случаи, когда некоторые объекты не могут быть равными или не равными (например, IEEE-754 NaN), но они выглядят как исключение, а не правило. Поэтому это не объясняет, почему разработчики компилятора С# сделали исключение правилом.
Я видел случаи плохого мастерства, в которых определяется оператор равенства, тогда оператор неравенства является копией-патчей, причем каждое сравнение обращается, и каждый && переключился на || (вы получаете смысл... в основном! (a == b), расширенный по правилам Де Моргана). Эта плохая практика, которую компилятор может устранить по дизайну, как в случае с Lua.
Примечание: То же самое справедливо для операторов < > <= > =. Я не могу представить случаи, когда вам нужно будет определить их неестественно. Lua позволяет вам определять только < и <= и определяет >= и > естественно через отрицание формеров. Почему С# не делает то же самое (по крайней мере, по умолчанию)?
ИЗМЕНИТЬ
По-видимому, есть веские причины, позволяющие программисту осуществлять проверки на равенство и неравенство, как им нравится. Некоторые из ответов указывают на случаи, когда это может быть приятно.
Ядро моего вопроса, однако, почему это принудительно требуется в С#, когда обычно это не логически необходимо?
Также поразительно контрастирует с выбором дизайна для интерфейсов .NET, таких как Object.Equals
, IEquatable.Equals
IEqualityComparer.Equals
, где отсутствие параллелиста NotEquals
показывает, что структура считает объекты !Equals()
неравными и что, Кроме того, классы типа Dictionary
и методы типа .Contains()
зависят исключительно от вышеупомянутых интерфейсов и не используют операторы напрямую, даже если они определены. Фактически, когда ReSharper генерирует члены равенства, он определяет как ==
, так и !=
в терминах Equals()
, и даже тогда, когда пользователь сам выбирает сгенерировать операторы. Операторы равенства не нужны платформой для понимания равенства объектов.
В принципе, платформа .NET не заботится об этих операторах, она заботится только о нескольких методах Equals
. Решение требовать, чтобы оба оператора == и!= Были определены в тандеме пользователем, относится исключительно к языковой конструкции, а не к семантике объектов, что касается .NET.