Проблема, которая здесь наблюдается, является частным случаем более общей проблемы, заключающейся в том, что количество различных определений равенства, которые могут быть полезны, по крайней мере, в некоторых обстоятельствах, превышает количество общедоступных средств их выражения. Эта проблема в некоторых случаях усугубляется неудачным убеждением в том, что использование разных средств проверки равенства приводит к разным результатам, сбивает с толку, и такой путаницы можно избежать, если различные формы равенства дают одинаковые результаты, когда это возможно.
На самом деле фундаментальной причиной путаницы является ошибочное убеждение, что следует ожидать, что разные формы проверки на равенство и неравенство дадут один и тот же результат, несмотря на тот факт, что разная семантика полезна в разных обстоятельствах. Например, с точки зрения арифметики полезно иметь возможность 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
если кто-то хочет проверить, является ли что-то нулевым.