bool? 与 bool 比较,GetValueOrDefault 和 ?? 运算符的区别是什么?

6

对于数字,它总是相同的漂亮

if(a < 123) { ... } // disregards if `b` is `int?` or `int`

但是使用bool?时:
bool? b = ...
if(b) { ... } // compiler error: can't convert bool? to bool.

以下是可选项:

if(b == false) { ... } // looks ugly, comparing bool? with bool
if(b.GetValueOrDefault()) { ... } // unclear when condition is true (one must know it's `false`)
if(b.GetValueOrDefault(true)) { ... } // required few seconds to understand inversion

我很好奇是否在使用nullables(至少是bool?)时,是否总是需要使用此语法:

if(b ?? false) { ... } // looks best to me

P.S.: 这可能看起来像基于个人意见的问题,但我无法独自解决所有疑惑......也许有些最好在特定场景中使用,我想知道哪些场景。


2
如果 bool 为空,你希望发生什么?应该执行 if 块,执行 else 块还是两者都不执行?答案取决于这一点,而你的示例在这方面做了不同的事情。 - Heinzi
2
@Heinzi,我故意选择了最令人困惑的情况。想象一下你读别人的代码或者为别人编写代码。你会选择哪个选项?为什么? - Sinatr
3个回答

13
语言设计者在允许 bool? 参与需要 bool 的控制语句的控制表达式方面有两种选择:
  • 允许,并在处理 null 时做出任意决策。
  • 禁止,强制您每次相关时都要做出决策。
请注意,设计者对于 if(a < 123) 语句问题的处理要少得多,因为对于“null 是否小于123”、“null 是否大于123”、“null 是否等于123”等问题,“否”是一个有效答案。 if (b ?? false)if (b ?? true) 是非常方便的结构,它们可以让您向代码读者和编译器解释您希望如何处理存储在 bool? 变量中的 null 值。

这是否意味着您自己更喜欢 ?? 解决方案?对我来说,它看起来最干净,指出了 b 可以是 null,并以最易理解的方式将 null 包含在条件中。 - Sinatr
@Sinatr 绝对没错,当处理可空类型中的 null 值时,?? 是最干净的解决方案。 - Sergey Kalinichenko
1
有趣的是,C# 设计者选择了选项 2,而 VB.NET 设计者(不幸地)选择了选项 1。 - Heinzi

5
每当我看到有人使用可空布尔值bool?时,我会问他们为什么这么做。通常的回答是--"嗯,我也不太确定"。实际上它创建了一个三状态的条件,我认为这使得代码阅读起来更加困难。如果它总是false,那null是什么意思,为什么一开始要将其设置为nullable呢?
但是更直接地回答你的问题,我更喜欢使用
if (b ?? false)

语法优于格式
if (b.GetValueOrDefault())

Nullable 类型非常有用(回答你的问题“为什么”)。随着 C# 6.0 的出现,?.(null-conditional 运算符)使它们变得更加实用。 - Sinatr
不要误会,我经常使用它们 - 但是当涉及到布尔值时,我尽可能避免使用三态布尔值,因为对我来说这就是二进制。特别是如果 null 始终为 false,那么三态布尔值并不是最佳实践。 - David Pine
大多数情况下,对我来说,bool? 用于列表比较,比如说: 如果(MyList?.FirstOrDefault(a => a == b)?.Value == c) 避免列表和结果的 if 语句,明确说明列表和搜索元素可以为 null,甚至可以扩展到 Value。 - GaelSa

3
几年后,从个人经验可以得出结论,以下语法显然是胜者:
if(b == false) { /* do something if false */ }
if(b == true) { /* do something if true */ }
if(b != false) { /* do something if NOT false, means true or null */ }
if(b != true) { /* do something if NOT true, means false or null */ }

我原以为“丑陋”的东西是最容易理解的。

== vs ??

可空类型通常是linq查询的结果,使用??会增加理解条件的不必要复杂度。

对比:

if(Items?.Any(o => o.IsSelected) == true)

vs

if(Items?.Any(o => o.IsSelected) ?? false)

第一个更容易阅读,它只需检查是否选择了任何项目。
当我(可能未受过训练的)大脑阅读后面一个代码块时,我需要在“??”处停顿思考,进行反转,然后才能理解“if”块将何时执行。由于存在“??”,当快速浏览他人编写的代码甚至经过足够长的时间后再查看自己的代码时,我很可能会犯错误。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接