Почему> = возвращает false, когда == возвращает true для нулевых значений?

76

У меня есть две переменные типа int? (или Nullable <int> если вы это сделаете). Я хотел бы сделать сравнение ( > =) по сравнению с двумя переменными, но, как оказалось, это возвращает false, если обе переменные равны нулю, а, очевидно, оператор == возвращает true.

Может кто-нибудь объяснить мне, почему это логично, потому что семантическое определение операторa >= содержит слово "или"?

  • 1
    Можете ли вы опубликовать код, который производит это странное поведение?
  • 12
    На самом деле, я бы спросил, уместно ли == возвращать true. Я не думаю, что это уместно на всех. Как две переменные, значение которых неизвестно, могут быть признаны равными?
Показать ещё 14 комментариев
Теги:
operators
comparison
nullable

7 ответов

90
Лучший ответ

Произошла огромная дискуссия об этой странности, когда функция была первоначально разработана в С# 2.0. Проблема в том, что пользователи С# полностью используют это значение:

if(someReference == null)

При расширении равенства к типам значений с нулевым значением у вас есть следующие варианты.

  • Неудачное равенство действительно отменено. Если один или оба операнда равны нулю, то результат не является ни истинным, ни ложным, но значением null. В этом случае вы можете:

    • a) Сделать недопустимым использование равенства типа nullable в выражении if, потому что для оператора if требуется bool, а не nullable bool. Вместо этого попросите всех использовать HasValue, если они хотят сравнить с нулем. Это многословно и раздражает.

    • b) Автоматически конвертировать значение null в значение false. Недостатком этого является то, что x==null возвращает false, если x равно null, что запутывает и работает против понимания людьми нулевых сравнений со ссылочными типами.

  • Невозможное равенство не снимается. Неверное равенство является либо истинным, либо ложным, а сравнение с null - это нулевая проверка. Это делает недействительным равенство несовместимым с нулевым неравенством.

Ни один из этих вариантов явно не прав; все они имеют за и против. Например, VBScript выбирает 1b. После долгих дебатов команда разработчиков С# выбрала № 2.

  • 0
    Как обнуляемое равенство несовместимо с обнуляемым неравенством в выборе № 2?
  • 3
    @MCS: Именно таким образом мотивируется вопрос. == может быть истиной, когда <= ложно.
Показать ещё 15 комментариев
58

Поскольку равенство определяется отдельно от сопоставимости.
Вы можете протестировать x == null, но x > null не имеет смысла. В С# он всегда будет ложным.

  • 1
    +1: вот ссылка на MSDN msdn.microsoft.com/en-us/library/2cf62fcy.aspx , но, к сожалению, они забыли объяснить поведение операторов сравнения в случае двух нулей (они упомянули только равенство) ...
  • 3
    да, но оператор больше или равен. Я вижу таблицу истинности, но я склонен согласиться с OP,> = больше или равно, если null == null true, null> = null также должно быть true. Я предполагаю, что мы просто связываем это с реализацией и удобством пользователя, чтобы сохранить == пустые проверки.
Показать ещё 1 комментарий
11

Другим способом описания " > =" является: Не меньше, чем. Никаких упоминаний о равных. Как только один из операндов в тесте без равенства равен Null, результат также неизвестен (равен null). Однако, если вы хотите знать, являются ли оба операнда Null, то Null == Null - разумный тест (должен привести к истине). Избавление от части неравенства оператора делает разницу.

Следующий пример кода из http://msdn.microsoft.com/en-us/library/2cf62fcy.aspx#sectionToggle4 показывает, как С# обрабатывает Null:

int? num1 = 10;   
int? num2 = null;   
if (num1 >= num2)   
{   
    Console.WriteLine("num1 is greater than or equal to num2");   
}   
else   
{   
    // This clause is selected, but num1 is not less than num2.   
    Console.WriteLine("num1 >= num2 returned false (but num1 < num2 also is false)");   
}   

if (num1 < num2)   
{   
    Console.WriteLine("num1 is less than num2");   
}   
else   
{   
    // The else clause is selected again, but num1 is not greater than   
    // or equal to num2.   
    Console.WriteLine("num1 < num2 returned false (but num1 >= num2 also is false)");   
}   

if (num1 != num2)   
{   
    // This comparison is true, num1 and num2 are not equal.   
    Console.WriteLine("Finally, num1 != num2 returns true!");   
}   

// Change the value of num1, so that both num1 and num2 are null.   
num1 = null;   
if (num1 == num2)   
{   
    // The equality comparison returns true when both operands are null.   
    Console.WriteLine("num1 == num2 returns true when the value of each is null");   
}   

/* Output:   
 * num1 >= num2 returned false (but num1 < num2 also is false)   
 * num1 < num2 returned false (but num1 >= num2 also is false)   
 * Finally, num1 != num2 returns true!   
 * num1 == num2 returns true when the value of each is null   
 */   
  • 0
    Это интересная ментальная модель. Однако в разделе § 1.4 спецификации C # эти операторы называются «меньше или равно» и «больше или равно»
  • 3
    @Conrad, который просто иллюстрирует проблемы перевода языка программирования (в данном случае C #) на английский. ИМХО, всякий раз, когда Nulls фигурируют в логике, вам нужно иметь дело с результатом с тремя состояниями (true, false, unknown). Любое выражение, включающее Null, должно приводить к unknown с единственным исключением Null == x которое является явным тестом для unknown, приводя либо к true, либо к false.
Показать ещё 1 комментарий
2

>= работает с числовым значением; который null не является.

Вы можете перегрузить оператор >=, чтобы обеспечить то, что вы хотите по определенному типу.

  • 0
    он работает с нулевыми типами, возвращает false
  • 0
    Он обрабатывает нулевые типы да ... семантика того, что мы собираемся определить как «работает». Защитное кодирование; если он равен нулю, тогда делайте x, а не лечите ноль как буквальное значение при принятии решений во время оценки.
Показать ещё 1 комментарий
0

>= означает только "больше или равно" при использовании в этом конкретном четко определенном виде. При использовании в классе с перегруженными операторами это означает все, что хочет сказать разработчик класса. При применении к строкоподобному классу это может означать, что "сортируется одинаково или выше", или может означать "ту же длину или дольше".

0

Какие значения вы ожидаете?

null == null true

null >= null false

null > null false

null <= null false

null < null false

null!= null false

1 == null false

1 >= null false

1 > null false

1 <= null false

1 < null false

1!= null true aka! (1 == null)

0

NULL не равен нулю (числовое или двоичное значение), строка нулевой длины или пустое (значение символа). Поэтому любой оператор сравнения всегда будет возвращать false. Подробнее об этом читайте здесь

  • 8
    База данных NULL не является C # null . Кроме того, операторы сравнения в C # обнуляемых типах - странный зверь, который не обязательно следует обычным правилам для нулевых сравнений.
  • 3
    Ответ все еще правильный, просто ссылка неправильная. msdn.microsoft.com/en-us/library/2cf62fcy.aspx#sectionToggle4
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню