Лучший способ проверить наличие обнуляемого bool в выражении условия (если…)


208

Мне было интересно, какой синтаксис был наиболее понятным и понятным для выполнения проверок условий на допускаемых значениях bools.

Это следующий хороший или плохой стиль кодирования? Есть ли способ выразить состояние лучше / чище?

bool? nullableBool = true;
if (nullableBool ?? false) { ... }
else { ... }

особенно часть if (nullableBool ?? false) . Мне не нравится if (x.HasValue && x.Value)стиль ...

(не уверен, задавался ли вопрос раньше ... не смог найти что-то похожее с поиском)

Ответы:


362

Я думаю, что многие люди сосредотачиваются на том факте, что эта ценность обнуляема, и не думают о том, чего они на самом деле хотят :)

bool? nullableBool = true;
if (nullableBool == true) { ... } // true
else { ... } // false or null

Или если вы хотите больше вариантов ...

bool? nullableBool = true;
if (nullableBool == true) { ... } // true
else if (nullableBool == false) { ... } // false
else { ... } // null

(nullableBool == true)никогда не вернет истину, если бул? является нулевым: P


2
Я не понимал, что такое обнуляемое сравнение было бы таким значимым. Подробности можно найти по адресу msdn.microsoft.com/en-us/library/2cf62fcy.aspx
Мика Золту

79

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

if (nullableBool.GetValueOrDefault(false)) {
}

6
В зависимости от контекста, который может использовать этот подходSystem.NotSupportedException: LINQ to Entities does not recognize the method 'Boolean GetValueOrDefault()' method, and this method cannot be translated into a store expression.
Nano Taboada

3
Мне нравится этот подход, так как он также работает в не-if-выражении (т.е. присваивании).
paultechguy

48

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

if (x.HasValue && x.Value)

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

Если вы берете свою версию и заменяете переменную на x, она также гласит:

if (x ?? false)

Это так ясно? Очевидно ли, что x это обнуляемый тип? Я позволю тебе решить.


Насколько мне известно, ?? работает только на обнуляемых типах. Плюс переменная должна иметь более приятное имя, чем x :)
FireSnake

5
Под «обнуляемым типом» я имел в виду типы System.Nullable. Любой тип ссылки может быть нулевым. Кроме того, если вам нужно использовать тип переменной как часть ее имени, это означает, что ваш код неясен.
Дэн Дипл

@DanDiplo Как написать UT для этого?
Прашант Ядав

xхорошо в контексте и иногда чище; для остроумия:var openOrders = orders.Where(x=>x.Open ?? false)
ничего лишнего

21

Если вы хотите трактовать a nullкак false, то я бы сказал, что наиболее краткий способ сделать это - использовать оператор null coalesce ( ??), как вы описываете:

if (nullableBool ?? false) { ... }

8

Просто подумай о буле? с 3 значениями все становится проще:

if (someNullableBool == true)     // only if true
if (someNullableBool == false)    // only if false
if (someNullableBool == null)     // only if null

8

Используйте расширения.

public static class NullableMixin {
    public static bool IsTrue(this System.Nullable<bool> val) {
        return val == true;
    }
    public static bool IsFalse(this System.Nullable<bool> val) {
        return val == false;
    }
    public static bool IsNull(this System.Nullable<bool> val) {
        return val == null;
    }
    public static bool IsNotNull(this System.Nullable<bool> val) {
        return val.HasValue;
    }
}


Nullable<bool> value = null;
if(value.IsTrue()) {
// do something with it
}

Что делать, если вы хотите рассмотреть nullкак true?
Thibault Falise

IsTrue () | IsNull () .. :) Я воспроизвел логику, как SQL работает с нулями. Я думаю, что это самый чистый и понятный синтаксис.
Андрей Фролов

Должно быть public static bool IsFalse (это System.Nullable val) {return! Val ?? правда; } считать ноль ложным
Майкл Фрейдгейм

2
В последних двух методах (например, IsNull и IsNotNull) могут отсутствовать точки с запятой (;)
Гленн Гарсон,

4

Давайте проверим, как определяется сравнение с нулем:

static void Main()
    {
        Console.WriteLine($"null != null  => {null != null}");
        Console.WriteLine($"null == null  => {null == null}");
        Console.WriteLine($"null != true  => {null != true}");
        Console.WriteLine($"null == true  => {null == true}");
        Console.WriteLine($"null != false => {null != false}");
        Console.WriteLine($"null == false => {null == false}");
    }

и результаты:

null != null  => False                                                                                                                                                                                                                                  
null == null  => True                                                                                                                                                                                                                                   
null != true  => True                                                                                                                                                                                                                                   
null == true  => False                                                                                                                                                                                                                                  
null != false => True                                                                                                                                                                                                                                   
null == false => False

Так что вы можете смело использовать:

// check if null or false
if (nullable != true) ...

// check if null or true
if (nullable != false) ...

// check if true or false
if (nullable != null) ...

Мне просто интересно, почему мы не можем сделать, если (nullable) .... это было бы ручкой, но нужно относиться с осторожностьюif(nullable)...else if(!nulllable)...else..
IronHide

Я бы сказал, что в последние годы стиль кодирования (из-за наличия таких инструментов, как stylecop, анализаторы и т. Д.) Все больше и больше предпочитает однозначный, понятный код «подтверждения намерений» (например, рекомендует использовать ненужные скобки только для подтверждения предполагаемого использования) приоритет операторов или использование различных систем аннотаций / контрактов). IMO, внедривший такой синтаксис, вызовет гораздо больше путаницы из-за уровня неясности того, как обрабатываются обнуляемые значения, чем пользы.
СЗ Moncz

4

На самом деле, я думаю, что (nullableBool ?? false)это законный вариант, особенно когда вы пытаетесь оценить nullable bool в linq.

Например:
array.Select(v => v.nullableBool ?? false)
(from v in array where v.nullableBool ?? false)

На мой взгляд, чище, а не:
array.Select(v => v.nullableBool.HasValue ? v.nullableBool.Value : false)
(from v in array where v.nullableBool.HasValue ? v.nullableBool.Value : false)


1

Если вы хотите только тест для trueAGAINST null/ false, Один я просто использовал и читает очень хорошо это

bool? someCondition = null
if (someCondition.Equals(true))
...

1
Вы не получаете исключение нулевой ссылки здесь?
Чейз Флорелл

@ChaseFlorell Я должен был дважды проверить это в интерактивном окне VS. Поэтому нужно помнить, что типом условия является Nullable <bool>. Вы все еще можете вызывать методы, унаследованные от объекта (например, Equals), HasValue и GetValueOrDefault , но не Value
ds4940

интересно, я вижу это сейчас. Все еще отрывочные для ссылочных типов dotnetfiddle.net/8cAI21
Чейз Флорелл

0

Я думаю, это до вас. Я, конечно, думаю, что подход .HasValue более читабелен, особенно с разработчиками, не знакомыми с ?? синтаксис.

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


0

Данное перечисление

public enum PublishMode { Edit, View }

Вы можете сделать это как здесь

 void MyMethod(PublishMode? mode)
    {
       var publishMode = mode ?? PublishMode.Edit;

//or
       if (mode?? PublishMode.Edit == someValue)
       ....
    }

Не ответ на вопрос, о котором конкретно идет речь nullable boolean.
ToolmakerSteve

0

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

if( someInt == 6 && someNullableBool == null ? false : (bool)someNullableBool){
    //perform your actions if true
}

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

Это, конечно, ручной способ сказать GetValueOrDefault(false)


3
Решение, представленное в OP, это то же самое, но с гораздо меньшим количеством кода. Это вовсе не выгодно для этого.
Servy
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.