Какая польза от типа Nullable <bool>? - PullRequest
11 голосов
/ 05 февраля 2010
Переменная

a bool может содержать значение true или false, в то время как bool? также может быть нулевой.

Зачем нам нужно третье значение для bool? Если это не истина , что бы это ни было, это == ложь

Можете ли вы предложить сценарий, в котором я хотел бы представить bool? .

Спасибо

Ответы [ 15 ]

32 голосов
/ 05 февраля 2010

Что-то может быть истинным, ложным или неопределенным по многим причинам. Как можно было бы ответить «Ваш третий ребенок - девочка?» если у одного только двое детей? И истина, и ложь неверны. Нулевым было бы уместно сказать, что сравнение не применимо.

13 голосов
/ 05 февраля 2010

Различные ответы обсуждают важность обнуляемых типов в целом. Существует дополнительный ответ для nullable boolean, в частности. Это трудно понять в C #, но очень легко понять, если вы посмотрите на нулевую логику в любой базе данных.

Допустим, вы отслеживаете список или таблицу Shipments. У Shipment есть DeliveryDate, но вы, конечно, не знаете эту информацию до тех пор, пока не будет произведена отгрузка, и, вероятно, по крайней мере, через несколько дней после ее фактической доставки, когда ИБП наконец получит уведомление. вы. Поэтому, конечно, DeliveryDate - это Nullable<DateTime> (или DateTime?).

Вы хотите получить список всех отправлений, которые были доставлены за последнюю неделю. Итак, вы пишете это:

var deliveredThisWeek = shipments.Where(s => 
    s.DeliveryDate >= DateTime.Today.AddDays(-7));

Должны ли быть включены грузы с датой доставки null? (Ответ, конечно, нет .)

ОК, так что же с этим:

var deliveredBeforeThisWeek = shipments.Where(s =>
    s.DeliveryDate < DateTime.Today.AddDays(-7));

Должны ли грузы с null датой поставки быть включены в эти результаты? Ответ до сих пор нет .

Так что теперь у вас любопытная ситуация. Вы можете подумать, что между этими двумя запросами вы получите все грузы в системе. A | !A всегда true, верно? Не тогда, когда вы имеете дело с нулями.

Даже этот не дает вам всех результатов:

var deliveredAnytime = shipments.Where(s =>
    (s.DeliveryDate >= DateTime.Today.AddDays(-7)) ||
    (s.DeliveryDate < DateTime.Today.AddDays(-7)));

Так как это возможно?

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

[DeliveryDate >= BeginningOfWeek] = NULL
[DeliveryDate <  BeginningOfWeek] = NULL

Очевидно, NULL OR NULL по-прежнему NULL, а не TRUE. Таким образом, вы можете правильно сказать, что посылка не была доставлена ​​до начала недели, и не были доставлены после. Или, точнее, мы не знаем когда оно было доставлено, поэтому мы не можем с уверенностью сказать, что оно соответствует ни одному из этих условий.

Но C # не такой последовательный. В C #, если DeliveryDate равно нулю, тогда:

(s.DeliveryDate >= beginningOfWeek) == false
(s.DeliveryDate < endOfWeek) == false

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

var deliveredThisWeek = shipments.Where(s =>
    !(s.DeliveryDate < DateTime.Today.AddDays(-7));

Ага ... теперь он возвращает нам null даты доставки! Это не правильно! И прежде чем кто-то скажет "@ Aaronaught, о чем ты, конечно, это правильно! Эти грузы НЕ были доставлены до прошлой недели, поэтому условие должно охватывать их!" , остановись и подумай об этом второй.

NULL на самом деле не означает, что они не были доставлены. NULL означает, что мы не знаем , когда они были доставлены. Вполне возможно, что клерк получит подтверждение завтра и заполнит DeliveryDate, как две недели назад, аннулируя данные, которые мы только что собрали. Должно быть , а не быть нулевыми экземплярами, возвращающимися из этого запроса, и все же они есть. Если вы напишете тот же запрос в SQL, эти результаты будут исключены.

Итак, почему вас должно волновать Nullable<bool>, когда C #, по-видимому, нет? Таким образом, вы можете избежать попадания в эту ловушку в своем собственном коде:

public static bool? IsThisWeek(DateTime? dt)
{
    return (dt != null) ? (bool?)(dt.Value > DateTime.Today.AddDays(-7)) : null;
}

var deliveredBeforeThisWeek = shipments.Where(s =>
    (!IsThisWeek(s.DeliveryDate) == true));

// Or, the equivalent:
var alsoDeliveredBeforeThisWeek = shipments.Where(s =>
    (IsThisWeek(s.DeliveryDate) == false));

Это немного неловко, но правильно. Мы написали запрос, который более или менее правильно сообщает о своем намерении, и (bool?)null не равно true или false, поэтому мы получаем правильные результаты в обоих случаях.

Если вам когда-либо понадобится оценить состояние, при котором ответ может быть «Я не знаю» - используйте bool? (AKA Nullable<bool>) в качестве результата .

Таким образом, вызывающий абонент может решить, как обрабатывать ответ «Я не знаю», а не просто выбирать значение по умолчанию. Все остальное означает, что ваш класс лжет .

10 голосов
/ 05 февраля 2010

a null значение означает «нет значения» или «неизвестное значение». В данном случае это не правда и не ложь, но undefined .

См .: http://en.wikipedia.org/wiki/Many-valued_logic

5 голосов
/ 05 февраля 2010

Это хорошо, когда что-то еще не ответили - подумайте о вопроснике. У вас есть список вопросов из года в год, и только на некоторые из них вы получили ответы. Вы не захотите публиковать значение true или false в таблице базы данных, поскольку пользователь еще не ответил на вопрос.

3 голосов
/ 05 февраля 2010

Ленивое программирование!

public bool MyProp
{
    get { return (myProp = myProp ?? GetPropValue()).Value; }
}
private bool? myProp;
3 голосов
/ 05 февраля 2010

это может быть неизвестно в дополнение к true или false .. в базе данных земля NULL обычно означает неизвестное или не имеет значения

2 голосов
/ 05 февраля 2010

Я использовал его в значении фильтра. По сути, у меня есть поле bool в базе данных, но я хотел три состояния: возвращать только те строки, где значение равно true, возвращать только те строки, где значение равно false, не фильтровать и возвращать все строки.

Без бульного значения, которое можно было бы обнулить, мне пришлось бы использовать перечисление или второй бул, чтобы определить «Фильтровать по этому полю да / нет», что добавило бы раздувание.

2 голосов
/ 05 февраля 2010

нулевое значение означает

  • Я не знаю.
  • Недостаточно данных в это время
  • Состояние кошки перед открытием ящика
  • Я еще не решил
  • Прибыль

нулевое значение означает Му

1 голос
/ 17 июня 2016

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

Недавно я неправильно обращался с Nullable bool. Я не буду вдаваться в детали ошибки, но скажу лишь, что она была достаточно плохой, чтобы потребовать полного отката. Я начал задаваться вопросом, насколько практично это использовать в большинстве приложений. (Частично в попытке удержать мою сломленную гордость в результате глупой ошибки ?)

Затем я наткнулся на этот пост, и Ли принял ответ.

Кажется, это имеет смысл, но чем больше времени я провожу с ним, на практике ответом становится ЛОЖЬ, а не NULL. NULL слишком нечеткий.

Прежде чем ответить на этот вопрос, нужно присвоить NULL очень специфическое значение. NULL означает, что произошла ошибка в расчете? Что если в вычислении будет допущена ошибка, прежде чем будет установлено, что существует только два ребенка? (Я также утверждаю, что если на самом деле есть только двое детей, это можно было бы решить до того, как вопрос был задан программе.)

Поскольку мы не знаем, что означает NULL, и потому, что оно определенно не ИСТИНА (потому что, как это могло быть?), ЛУЧШИЙ ответ - ЛОЖЬ.

Кроме того, если этот вопрос действительно возвращает NULL, мы ввели новое определение для домена. Каков охват этого определения?

Таким образом, может показаться, что состояния ИСТИНА или ЛОЖЬ представляют определенность в отношении результата. NULL может быть представлен как минимум в трех разных состояниях. Например, утверждение «Томас пошел в бар прошлой ночью».

ИСТИНА - Да, Томас пошел в бар. (наиболее вероятный ответ, если вы знали Томаса) ЛОЖЬ - Нет, Томас не пошел в бар. NULL - А? Узнаваемый - что-то пошло не так в первом расчете. Например. Вы задали вопрос Томасу, но чихнули, пока он отвечал, на мгновение оглушая вас. Просто спросив его снова, вы получите ответ.

Неизвестно - Бар сгорел, и Томас пропустил город. Не существует реалистичного способа получить ответ. (Пожалуйста, не пробивайте дыры в этом, но я знаю, что вы это сделаете)

Не применимо - см. Пример выше, касающийся троих детей, но вместо них бары и томазы.

Что здесь означает NULL? Определение значения NULL должно выполняться в каждом конкретном случае. Вот почему я считаю, что часто лучше использовать Enum или другую структуру, так как она более изящно раскрывает намерение за недвоичным возвращаемым значением.

1 голос
/ 05 февраля 2010

Ну, я могу видеть, что это используется как "еще не определено", я использую bools все время, а иногда просто двух значений недостаточно !! например:

bool? bl;

bl = true; //Yes

bl = false; //No

bl = null; // Not determined, so do nothing

по-моему, это всего лишь третье значение для bool.

...