2010-07-07 5 views
20

По этой причине null не оценивается до false в условных обозначениях?Почему значение null не равно false?

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

if (someClass = someValue) // cannot convert someClass to bool. Ok, nice 

if (someClass) // Cannot convert someClass to bool. Why? 

if (someClass != null) // More readable? 

Я думаю, что это довольно разумно предположить, что null означает false. Есть и другие языки, которые тоже используют это, и из-за этого у меня не было ошибки.

Редактировать: И я, конечно, ссылаюсь на ссылочные типы.

Хороший комментарий Даниэль Earwicker на ошибку назначениях ... компилируется без предупреждения, потому что он имеет значение bool:

bool bool1 = false, bool2 = true; 
if (bool1 = bool2) 
{ 
    // oops... false == true, and bool1 became true... 
} 
+0

Простой ответ: «Так хотели дизайнеры C#». Но это не отвечает на вопрос. Кто-нибудь знает, почему разработчикам языка не нравилось автоматическое литье ссылок на булевы (например, C/C++/Python)? – Karmastan

+0

Я пытаюсь отследить ссылку - я думаю, что мне удалось поговорить с одной из языковых команд некоторое время назад, что на самом деле не помогает –

+0

Я думаю, что только программисты C сочтут разумным, что null означает false. False - значение, null - отсутствие значения. Я считаю, что C# правильно это понимает. Другие языки, которые были построены без логического типа или понятия указателя (или типа NULL), просто перегружали int, чтобы означать все эти разные вещи. Почему NULL == false и false == 0? Они не должны. – Dolphin

ответ

21

Это специфическая особенность конструкции в языке С #: if statements accept only a bool.

IIRC это для безопасности: специально, чтобы ваш первый if (someClass = someValue) не смог скомпилировать.

Редактировать: Одно из преимуществ заключается в том, что оно делает ненужным соглашение (0).

+0

Но вместо того, чтобы говорить «только принимает bool», он может сказать «не принимает присваивание» ... – simendsjo

+1

Да, я считаю, что поведение C# предпочтительнее здесь, в частности, потому что оно защищает вас от этой общей ошибки. –

+1

Присвоение как условие полезно, хотя и не так много в операторах 'if':' while ((line = Console.ReadLine())! = null) ' –

5

Одна вещь, которая приходит на ум, о чем в экземпляре типа данных, например int? Int не может быть нулевым, так что они всегда оценивают true? Вы можете предположить, что int = 0 является ложным, но это начинает становиться действительно сложным, потому что 0 является допустимым значением (где, возможно, 0 должно оцениваться как true, потому что прогамер его установил), а не только по умолчанию.
Существует множество случаев, когда null не является вариантом, или иногда это вариант, а иногда - нет.

Они ставят такие вещи, чтобы защитить программиста от ошибок. Это идет по той же линии, почему вы не можете провалить в заявлениях о случаях.

+1

+1 NULL означает, что значение неизвестно или значение отсутствует или значение еще не назначено и т. Д. Это не означает FALSE, семантически они не совпадают. Я всегда думаю, что лечение NULL, поскольку FALSE - плохой дизайн языка. – Liwen

+0

@ Liwen Я согласен. На первый взгляд кажется, что это может иметь смысл, но есть слишком много возможностей, где значения null и false будут отличаться. – kemiller2002

+0

Но тип valuetype не является ссылочным типом и не может быть нулевым. Я не говорю, что каждый возможный тип, отличный от false, должен оцениваться как true ... – simendsjo

4

Насколько я знаю, это особенность, которую вы видите на динамических языках, что C# не является (согласно спецификации языка if принимает только bool или выражение, которое bool).

Я не думаю, что это разумно предположить, что null в каждый случае false. Это имеет смысл в некоторых случаях, но не в других. Например, предположим, что у вас есть флаг, который может иметь три значения: set, unset и un-initialized. В этом случае установить будет true, незаданы будет false и ун-инициализирован будут null. Как вы можете видеть, в этом случае значение null не равно false.

+1

Лошади набрал ≠ динамически типизировал. C++ оценивает 'NULL' (макрос) значение' 0', которое затем вычисляет 'false' в инструкции' if'. – strager

+1

Я не говорил о 'NULL'. Я говорил о «нулевом». Я не вижу, как мое оригинальное утверждение ошибочно. Обычно вы видите 'if (someVarThatCouldBeNull)' в динамических языках. –

+0

Согласен, Вивинь. Я бы сказал, что понятие null не существует в C++. Вернее, понятие переменной без значения (т. Е. Null в C#) не существует в C++. Переменная всегда будет иметь значение, вы просто не знаете, что это такое, если вы не инициализируете ее самостоятельно. Как указывает strager, NULL в C++ - это просто макрос, представляющий 0, не более того. Вокруг него нет специальных правил компиляции. –

19

«Я думаю, что это довольно разумно предположить, что нуль означает ложное»

Не в C#.false - это логическая структура, тип значения. Типы значений не могут иметь нулевое значение. Если вы хотите, чтобы делать то, что вы достигли, вы должны создавать пользовательские конвертеры для вашего конкретного типа в булево:

public class MyClass 
{ 
    public static implicit operator bool(MyClass instance) 
    { 
     return instance != null; 
    } 
} 

С выше, я мог бы сделать:

if (instance) { 

} 

и т.д.

+0

Вы также можете использовать операторы true или false, хотя они немного скрыты: http://msdn.microsoft.com/en-us/library/6x6y6z4d%28VS.80%29.aspx –

+0

На боковой ноте, интересным следствием использования истинных и ложных операторов является то, что конкретное состояние может быть истинным, ложным, ни тем, ни другим. Это означает, что тип, реализующий истинные и ложные операторы, может удовлетворять выражению 'Debug.Assert (x &&! X)' –

+0

Это то, что я искал, у меня есть объект статуса, и я хотел иметь возможность делать 'if (status) {} 'вместо' if (status.isSuccess()) {} '. Я все еще не уверен, что это хорошая идея, но теперь я могу это сделать. –

5

Просто используйте, если (Convert.ToBoolean (SomeClass))

http://msdn.microsoft.com/en-us/library/wh2c31dd.aspx

Параметры

Значение Тип: System.Object Объект, который реализует интерфейс IConvertible или нуль. Возвращаемое значение

Тип: System.Boolean истинным или ложным, , которое отражает значение, возвращаемое вызовом метода IConvertible.ToBoolean для базового типа значения. Если значение равно нулю, метод возвращает false

2

C# не делает преобразование параметра, как это делает C++. Вам нужно явно преобразовать значение в логическое значение, если вы хотите, чтобы оператор if принял значение.

13

«Я думаю, что это довольно разумно предположить, что нуль означает ложь»

я не согласен. ИМХО, чаще всего, ложно означает «нет». Null означает «я не знаю»; т.е. полностью неопределенным.

+3

+1 - делает NULL * ever * означает false? Я не могу придумать никаких примеров технологии, которая реализована таким образом. Могут быть некоторые, которые неявно допускают сравнения, но afaik, null никогда не означает false. – womp

+0

Хотя я не эксперт на разных языках, я думаю, что NULL, вероятно, только когда-либо «означает» ложь на языке, который в первую очередь не обрабатывает NULL. –

3

Потому что null и false - это разные вещи.

Прекрасным примером является bool? foo

Если значение foo истинно, тогда его значение равно true.
Если значение foo является ложным, то его значение равно false
Если foo ничего не присвоено ему, его значение равно null.

Это три логически отдельных условия.

думать об этом еще один способ
«Сколько денег я вам должен?»
«Ничего» и «у меня нет этой информации» два совершенно отдельных ответов.

+0

+1 для хорошей точки, но все же .. Если вы попытаетесь оценить bool? вам нужно либо бросить его на bool, либо получить ошибку выполнения, либо использовать == true/false для его оценки ... bool? не является ссылочным типом в качестве моего вопроса, он по-прежнему является ценностным типом. – simendsjo

+1

Как примечание, компьютер должен знать ответы на вопросы о данных и, вероятно, должен сигнализировать об ошибке, если что-то «не может быть определено». – Victor

3

В чем причина null: оценивается как false в условных выражениях?

Я сначала подумал о присвоений избежать ошибки использования = вместо ==

Это не причина.Мы знаем это, потому что если две переменные сравниваются случается типа bool, то код будет компилироваться вполне счастливо:

bool a = ... 
bool b = ... 

if (a = b) 
    Console.WriteLine("Weird, I expected them to be different"); 

Если b верно, то выводится сообщение (и a теперь является истинным, что делает последующее отладки опыт в соответствии с сообщением, что вводит в заблуждение вас еще больше ...)

причина null не конвертируется в bool просто, что C# позволяет избежать неявного преобразования, если не требуется конструктором, определенного пользователем типа. Книга истории C++ полна болезненных историй, вызванных неявными преобразованиями.

+0

Я уже обновил свой вопрос с этим с вашего предыдущего комментария. Неявный аргумент преобразования - лучшее, что я слышал до сих пор. – simendsjo

1

Это просто тип системы C# по сравнению с языками, как PHP, Perl и т.д.

Условие принимает только Boolean значения, нуль не имеет тип Boolean поэтому он не работает там.

Что касается примера NULL в C/C++, о котором вы упомянули в другом комментарии, то нужно сказать, что ни C, ни C++ не имеют логического типа (afair C++ обычно имеет тип для bool, который разрешает int, но это другое материи), и они также не имеют нулевых ссылок, а только NULL (=> 0) -поточников.

Конечно конструкторы компилятор может реализовать автоматическое преобразование для любого обнуляемого типа для булева но может вызвать другие проблемы, а именно:

Если предположить, что foo является неnull:

if (foo) 
{ 
    // do stuff 
} 

Какие состояние foo истинно?
Всегда, если это не null?
Но что, если вы хотите, чтобы ваш тип мог быть преобразован в логическое (т. Е. Из вашего трехгосударственного или квантово-логического класса)?

Это означало бы, что у вас будет два разных преобразования в bool, неявное и явное, которое будет вести себя по-другому.

Я даже не смею представить, что должно произойти, если вы

if (!!foo) // common pattern in C to normalize a value used as boolean, 
      // in this case might be abused to create a boolean from an object 
{ 
} 

Я думаю, что вынужденное (foo == null) хорошо, поскольку она также вносит ясность в ваш код, это легче понять, что вы на самом деле проверить ,

3

Структурно большинство людей, которые «не могут думать о какой-либо технологической причине null, должны быть равны ложному», ошибаются.

Код управляется процессорами. Большинство (если не все) процессоров имеют бит, группы бит и интерпретации групп бит. Тем не менее, что-то может быть 0, 1, a byte, a word, a dword, a qword и так далее.

Обратите внимание, что на платформе x86 байты - октеты (8 бит), а слова обычно 16 бит, но это не является необходимостью. Старые процессоры имели слова 4 бит, и даже сегодняшние «низкоуровневые» встроенные контроллеры часто используют как 7 или 12 бит на слово.

Это говорит о том, что в машинный код что-то есть «равно», «ноль», «больше», «меньше», «больше или равно» или «меньше или равно». Нет такой вещи, как null, false или true.

В конвенции, true является 1, false является 0 и null указатель либо 0x00, 0x0000, 0x00000000 или 0x0000000000000000, в зависимости от адресной шины ширины.

C# является одним из исключений, так как она является косвенным типа, где два возможных значения 0 и 1 не непосредственное значение, но индекс структуры (вспомним enum в C, или PTR в x86 монтаж).

Это по дизайну.

Важно отметить, однако, что такие дизайнерские решения сложных решения, в то время как традиционных, простой способ заключается в предположении, что 0, null и false равны.

Смежные вопросы