Проблема, которая здесь наблюдается, является частным случаем более общей проблемы, заключающейся в том, что количество различных определений равенства, которые могут быть полезны, по крайней мере, в некоторых обстоятельствах, превышает количество общедоступных средств их выражения. Эта проблема в некоторых случаях усугубляется неудачным убеждением в том, что использование разных средств проверки равенства приводит к разным результатам, сбивает с толку, и такой путаницы можно избежать, если различные формы равенства дают одинаковые результаты, когда это возможно.
На самом деле фундаментальной причиной путаницы является ошибочное убеждение, что следует ожидать, что разные формы проверки на равенство и неравенство дадут один и тот же результат, несмотря на тот факт, что разная семантика полезна в разных обстоятельствах. Например, с точки зрения арифметики полезно иметь возможность Decimalсравнивать те , которые отличаются только количеством конечных нулей, как равные. То же самое для doubleтаких значений, как положительный ноль и отрицательный ноль. С другой стороны, с точки зрения кэширования или интернирования такая семантика может быть смертельной. Допустим, например, у одного есть Dictionary<Decimal, String>такой, на который myDict[someDecimal]должно равняться someDecimal.ToString(). Такой объект казался бы разумным, если бы у него было многоDecimalзначения, которые нужно было преобразовать в строку и ожидалось, что будет много дубликатов. К сожалению, если использовать такое кэширование для преобразования 12,3 м и 12,40 м, а затем 12,30 м и 12,4 м, последние значения дадут «12,3» и «12,40» вместо «12,30» и «12,4».
Возвращаясь к рассматриваемому вопросу, существует более одного разумного способа сравнения обнуляемых объектов на предмет равенства. C # придерживается точки зрения, что его ==оператор должен отражать поведение Equals. VB.NET придерживается точки зрения, что его поведение должно отражать поведение некоторых других языков, поскольку любой, кто хочет, Equalsможет использовать его Equals. В некотором смысле правильным решением было бы иметь трехстороннюю конструкцию «if» и требовать, чтобы, если условное выражение возвращает трехзначный результат, код должен указывать, что должно происходить в nullслучае. Поскольку это не вариант с языками как они есть, следующая лучшая альтернатива - просто изучить, как работают разные языки, и признать, что они не совпадают.
Между прочим, оператор «Is» в Visual Basic, которого нет в C, можно использовать для проверки того, действительно ли объект, допускающий значение NULL, равен NULL. Хотя можно резонно задаться вопросом, ifдолжен ли тест принимать a Boolean?, наличие обычных операторов сравнения, возвращаемых Boolean?вместо того, чтобы Booleanвызывать их для типов, допускающих значение NULL, является полезной функцией. Между прочим, в VB.NET, если кто-то попытается использовать оператор равенства, а не Is, вы получите предупреждение о том, что результат сравнения всегда будет Nothing, и его следует использовать, Isесли кто-то хочет проверить, является ли что-то нулевым.