在条件表达式中检查可空布尔的最佳方法(如果…)


207

我想知道在对可空布尔进行条件检查时最干净,最易懂的语法是什么。

以下的编码风格是好是坏?有没有一种更好/更干净地表达条件的方法?

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

尤其是if(nullableBool ?? false)部分。我不喜欢这种if (x.HasValue && x.Value)风格...

(不确定是否曾经问过这个问题……无法在搜索中找到类似的内容)

Answers:


361

我认为很多人都在关注这个值是可为空的事实,而不考虑他们真正想要的是什么:)

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)如果布尔将永远不会返回true?为空:P


2
我没有意识到像这样的可空比较是有意义的。有关详细信息,请访问msdn.microsoft.com/en-us/library/2cf62fcy.aspx
Micah Zoltu 2015年

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 2010年

5
“可空类型”是指System.Nullable类型。任何引用类型都可以为null。另外,如果您需要使用变量的类型作为其名称的一部分,则表明您的代码不清楚。
Dan Diplo

@DanDiplo如何为此编写UT?
Prashant Yadav

x在上下文中很好,有时更干净;智慧:var openOrders = orders.Where(x=>x.Open ?? false)
没必要,

21

如果您想将a null视为假,那么我会说,最简洁的方法是使用null合并运算符(??),如下所述:

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
}

如果你要考虑nulltrue
Thibault Falise 2010年

IsTrue()| IsNull().. :)我复制了SQL如何使用null的逻辑。我认为这是最干净易懂的语法。
Andrey Frolov

它应该是公共静态布尔IsFalse(this System.Nullable val){return!val?真正; }将null视为错误
Michael Freidgeim

2
在后两种方法(即IsNull和IsNotNull)中可能缺少分号(;)
glenn garson 2014年

4

让我们检查一下如何定义与null的比较:

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) ...

我只是想知道为什么我们不能做if(nullable)....那会得到解决,但需要谨慎对待if(nullable)...else if(!nulllable)...else..
IronHide

我想说,在过去的几年中,编码风格(由于使用了stylecop,分析器等工具)越来越倾向于使用明确,清晰,“意图确认”的代码(例如,建议使用不需要的括号以确认预期的用法)运营商的优先级,或使用各种注释/合同系统)。IMO引入这种语法会造成更多的混乱,这是由于不确定如何处理可为空值而不是受益的程度。
Sz。Moncz

4

实际上,我认为这(nullableBool ?? false)是一个合理的选择,尤其是当您尝试在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

如果您只想true针对null/ 进行测试false,那么我刚刚使用过的一个文件就读得很好。

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

1
您没有在这里得到空引用异常吗?
Chase Florell

@ChaseFlorell我必须在VS Interactive窗口中再次检查它。.因此要记住的是,某种条件的类型是Nullable <bool>。您仍然可以调用从对象继承的方法(例如Equals),HasValue和GetValueOrDefault ,但没有价值
ds4940

有趣的是,我现在可以看到。对于引用类型,仍是粗略的dotnetfiddle.net/8cAI21
Chase Florell

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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.