Каково использование типа Nullable <bool>?

bool переменная могла сохраняться или ложь, в то время как bool? могло быть пустым также.

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

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

Спасибо

12
задан Asad 6 February 2010 в 16:07
поделиться

14 ответов

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

34
ответ дан 2 December 2019 в 02:52
поделиться

допускающий значение NULL может означать, что логическое значение не было установлено или инициализировано, если это то, что вашей программе может потребоваться знать

1
ответ дан 2 December 2019 в 02:52
поделиться

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

3
ответ дан 2 December 2019 в 02:52
поделиться

Я думаю, что основная мотивация (по крайней мере, она была представлена ​​так :-)) для добавления типов, допускающих значение NULL, в C # 2 были базами данных.В базе данных любой тип данных может иметь значение NULL , и при отображении их на C # это проблема. Обнуляемые типы позволяют справиться с этим довольно элегантно - вы можете использовать int? , bool? и другие. Они используются, например, в LINQ to SQL.

Что означает третье значение для логических значений, это, конечно, зависит от приложения. Я предполагаю, что обычно это будет означать, что значение / поле недоступно.

0
ответ дан 2 December 2019 в 02:52
поделиться

Допустим, заказ был размещен, но еще не отправлен. Каково значение Order.ShippedDate ?

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

Таким образом, современный подход состоит в том, чтобы разрешить Order.ShippedDate принимать значение, семантически фиксирующее, что заказ еще не отправлен. Эту роль играют типы, допускающие значение NULL.Семантически вы должны думать об экземпляре Nullable с HasValue , являющимся ложным , как представляющий «отсутствует» или «неизвестно»

. Кроме того, базы данных. давно разрешили столбцу разрешить null . Например, у вас может быть целочисленный столбец, допускающий значение NULL. Как вы взаимодействуете с таким столбцом из кода, если вы не разрешаете допускающие значение NULL int s? Опять же, вы можете использовать упомянутые выше подходы, но это намного лучше, когда в языке есть встроенные средства для семантического захвата ситуации, которую мы пытаемся смоделировать.

0
ответ дан 2 December 2019 в 02:52
поделиться

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

bool? bl;

bl = true; //Yes

bl = false; //No

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

на мой взгляд, это всего лишь третье значение для буллы.

1
ответ дан 2 December 2019 в 02:52
поделиться

пустое значение означает

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

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

2
ответ дан 2 December 2019 в 02:52
поделиться

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

public bool MyProp
{
    get { return (myProp = myProp ?? GetPropValue()).Value; }
}
private bool? myProp;
3
ответ дан 2 December 2019 в 02:52
поделиться

Начните с первого элемента и последовательно. При этом искать второй элемент с помощью двоичного поиска.

-121--5044501-

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

-121--5044502-

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

5
ответ дан 2 December 2019 в 02:52
поделиться

a нулевое значение означает "нет значения" или "неизвестное значение". В данном случае это не истинно и не ложно, но неопределенное.

Смотрите: http://en.wikipedia.org/wiki/Many-valued_logic

10
ответ дан 2 December 2019 в 02:52
поделиться

Я думаю, что основной мотивацией (по крайней мере, она была представлена так: -)) для добавления типов с нулевым значением в C # 2 были базы данных. В базе данных любой тип данных может иметь значение NULL , и при сопоставлении их с C # это является проблемой. Ничтожные типы позволяют бороться с этим довольно элегантно - можно использовать int? , bool? и другие. Они используются, например, в LINQ-SQL.

Что означает третье значение для booleans, это, конечно, зависит от применения. Я думаю, что обычно это будет означать, что значение/поле недоступно.

-121--2739761-

F #: 355 значимые символы

Все в одной строке:

let[|x;y|]=System.Console.ReadLine().Split([|' '|])in[for i in 1..9->let r (a:string) b j (s:string)=s.Replace(a,if i>j then b else a)in((String.replicate(int y+1)"23012123012121").Substring(int(x.[0])-65,int y*2+x.Length).Replace("0","|   ")|>r"1""#"0|>r"2""##  "0|>r"3"" "0).TrimEnd()|>r"###"" | "5|>r"##""| "5|>r" ""_"8]|>String.concat"\n"|>printfn "%s"

Расширенный:

let piano() =
    let[|x;y|]=System.Console.ReadLine().Split([|' '|])in
    [for i in 1..9->
        let r (a:string) b j (s:string) = s.Replace(a,if i>j then b else a) in
        ((String.replicate (int y+1) "23012123012121")
            .Substring(int(x.[0])-65,int y*2+x.Length).Replace("0","|   ")
            |> r "1" "#" 0
            |> r "2" "##  " 0
            |> r "3" " " 0)
            .TrimEnd()|> r "###" " | " 5|> r "##" "| " 5|> r " " "_" 8]
    |> String.concat "\n"
    |> printfn "%s"
-121--778764-

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

Допустим, вы отслеживаете список или таблицу Отгрузки . Отгрузка имеет дату доставки , но, конечно, вы не знаете эту информацию до тех пор, пока отгрузка не будет произведена, и, вероятно, по крайней мере через несколько дней после фактической доставки, когда UPS наконец получит уведомление. Таким образом, DeliviveDate является значением Null < DateTime > (или DateTime? ).

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

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

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

OK, так что насчет этого:

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

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

Итак, сейчас у вас любопытная ситуация. Можно подумать, что между этими двумя запросами будут получены все транспортировки в системе. 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 или NULL по-прежнему NULL , а не TRUE . Именно так можно правильно сказать, что отгрузка не была доставлена до начала недели, и не была доставлена после. Или, точнее, мы не знаем , когда он был доставлен, поэтому мы не можем безопасно сказать, что он соответствует любому из этих условий.

Но C # не является таким последовательным. В C #,если DeliviveDate имеет значение null, то:

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

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

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

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

Значение NULL на самом деле не означает, что они не были доставлены. NULL означает, что мы не знаем , когда они были доставлены. Возможно, что клерк заберет подтверждение завтра и заполнит DeliviveDate , как и две недели назад, признав недействительными только что собранные данные. Экземпляры не должны быть NULL, возвращающиеся из этого запроса, и все же их существует. При написании одного и того же запроса в SQL эти результаты будут исключены.

Итак, почему нужно иметь дело с нулевым значением < 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 > ) в результате .

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

14
ответ дан 2 December 2019 в 02:52
поделиться

F #: 355 значимые символы

Все в одной строке:

let[|x;y|]=System.Console.ReadLine().Split([|' '|])in[for i in 1..9->let r (a:string) b j (s:string)=s.Replace(a,if i>j then b else a)in((String.replicate(int y+1)"23012123012121").Substring(int(x.[0])-65,int y*2+x.Length).Replace("0","|   ")|>r"1""#"0|>r"2""##  "0|>r"3"" "0).TrimEnd()|>r"###"" | "5|>r"##""| "5|>r" ""_"8]|>String.concat"\n"|>printfn "%s"

Расширенный:

let piano() =
    let[|x;y|]=System.Console.ReadLine().Split([|' '|])in
    [for i in 1..9->
        let r (a:string) b j (s:string) = s.Replace(a,if i>j then b else a) in
        ((String.replicate (int y+1) "23012123012121")
            .Substring(int(x.[0])-65,int y*2+x.Length).Replace("0","|   ")
            |> r "1" "#" 0
            |> r "2" "##  " 0
            |> r "3" " " 0)
            .TrimEnd()|> r "###" " | " 5|> r "##" "| " 5|> r " " "_" 8]
    |> String.concat "\n"
    |> printfn "%s"
-121--778764-

Я не думаю, что использование только '#' является хорошим. Это не очень важно для пользователя.

Вам не нужно определять дополнительный идентификатор, просто чтобы использовать его для привязки к верхней части страницы. Гораздо лучше использовать существующий элемент на странице. Например, при наличии логотипа в верхней части страницы можно присвоить тегу < img > идентификатор «top»:

<img src="logo.png" id="top">

В нижней части страницы можно использовать этот идентификатор элемента для перехода в верхнюю часть страницы:

<a href="#top" title="Go to top of page">Go to top of page</a>

Это приведет к http://www.mysite.com/#top , что будет более значимым для посетителей.

-121--3147230-

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

Без пуля с нулевым значением мне пришлось бы использовать либо перечисление, либо второе пуло, чтобы определить «Filter by this поля yes/no», что добавило бы вздутие.

2
ответ дан 2 December 2019 в 02:52
поделиться

Стандарт C++ (по крайней мере C++ 98) не имеет отношения к организации сети ни в одном пути. Таким образом, вы должны сделать что-то специфичное для платформы.

Некоторые платформы имеют реализации IOStreams, которые позволяют создавать поток из дескриптора файла. В этом случае используйте дескриптор сокета в качестве дескриптора файла.

-121--2672272-

Это действительно вопрос о суррогатных ключах, которые всегда являются либо автоматически увеличивающимся числом, либо GUID и, следовательно, одним столбцом, в сравнении с естественными ключами, которые часто требуют нескольких частей информации, чтобы быть действительно уникальными. Если у вас есть естественный ключ, который является только одним столбцом, то точка в любом случае явно спорная.

Некоторые люди будут настаивать только на использовании того или иного. Потратьте достаточно времени на работу с производственными базами данных, и вы узнаете, что нет независимой от контекста передовой практики.

Некоторые из этих ответов используют терминологию SQL Server, но эти концепции обычно применимы ко всем продуктам СУБД:


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

  • Кластеризованные индексы. Кластеризованный индекс всегда работает лучше, когда база данных может просто добавить к нему - в противном случае БД должна выполнить разделение страницы . Следует отметить, что это применимо только в том случае, если клавиша имеет значение sequential , т.е. последовательность автоприращения или последовательный GUID. Произвольные GUID, вероятно, будут намного хуже для производительности.

  • Отношения. Если ваш ключ имеет длину 3, 4 5 столбцов, включая символьные типы и другие некомпактные данные, вы теряете огромное пространство и впоследствии снижаете производительность, если вам приходится создавать связи внешнего ключа с этим ключом во 20 других таблицах.

  • Уникальность. Иногда у вас нет истинного естественного ключа. Может быть, ваш стол - это какой-то журнал, и вы можете получить два одних и тех же события одновременно. Или, может быть, ваш реальный ключ - это что-то вроде материализованного пути, который может быть определен только после того, как строка уже вставлена. В любом случае, вы всегда хотите, чтобы ваш кластеризованный индекс и/или первичный ключ был уникальным, поэтому, если у вас нет другой действительно уникальной информации, у вас нет другого выбора, кроме как использовать суррогатный ключ.

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

Причины использования многоколонных натуральных ключей

  • Мест хранения. Многие люди, которые работают с базами данных, никогда не работают с достаточно большими, чтобы заботиться об этом факторе.Но когда в таблице есть миллиарды или триллионы строк, вы захотите сохранить абсолютный минимум данных в этой таблице, который вы, возможно, можете.

  • Репликация. Да, можно использовать GUID или последовательный GUID. Но GUID имеют свои собственные компромиссы, и если вы не можете или не хотите использовать GUID по какой-то причине, многоколонный естественный ключ является гораздо лучшим выбором для сценариев репликации, потому что он по сути глобально уникален - то есть вам не нужен специальный алгоритм, чтобы сделать его уникальным, он уникален по определению . Это очень упрощает анализ распределенных архитектур.

  • Вставить/обновить производительность . Суррогатные ключи не бесплатны. Если имеется набор столбцов, которые являются уникальными и часто запрашиваются, и поэтому для этих столбцов необходимо создать индекс покрытия; индекс становится почти таким же большим, как таблица, что приводит к растрате пространства и , что требует обновления второго индекса при каждом внесении изменений. Если вы когда-либо можете иметь только один индекс (кластеризованный индекс) в таблице, вы должны сделать это!


Вот что приходит в голову прямо с летучей мыши. Я обновлю, если вдруг вспомню что-нибудь еще.

-121--2435793-

Вот еще один пример использования. Представьте иерархическую структуру данных, имеющую логическое свойство. Установка такого свойства для родительского элемента будет применяться ко всем его дочерним элементам, если они не заданы явно. Подумайте, что разрешения только для чтения для файлов и папок в Windows (у которых DO есть флажок с тремя состояниями).

Parent1(readonly: true, evaluates true)
  |-Parent2(readonly: null, evaluates true)
    |-Child1(readonly: false, evaluates false)
    |-Child2(readonly: null, evaluates true)
 |-Parent3(readonly: false, evaluates false)
    |-Child1(readonly: false, evaluates false)
    |-Child2(readonly: null, evaluates false)
0
ответ дан 2 December 2019 в 02:52
поделиться

Вы бы хотели использовать это, чтобы охватить ситуацию «что, если пользователь не указывает ни истину, ни ложь?»

Это просто способ охватить все возможные результаты.

0
ответ дан 2 December 2019 в 02:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: