在条件语句中使用null条件运算符时,如何处理null大小写?

时间:2019-02-19 04:21:28

标签: c# .net

说我在这里有以下代码:

static void Main(string[] args)
{
   StringBuilder[] s = new StringBuilder[3];
   if (s[0]?.Length > 0)
   {
       Console.WriteLine("hi");
   }
}

我的理解是if语句内的表达式必须是布尔表达式。布尔表达式(我的理解可能是错误的)是计算结果为true或false的表达式。

在这种情况下,空条件运算符将返回空值,因为引用类型变量数组中元素的默认值是空值。因此,此if语句等效于

bool? x = null;
if (x)
{ 
   // do cool things here */ 
}

但这给了我一个语法错误:无法将null转换为bool。

因此,上述带有StringBuilder的示例如何运作?我的理解是,上面代码的更好方法是将其与null运算符结合使用,如:

if (s[0]?.Length > 0 ?? false) {}

谢谢:)

3 个答案:

答案 0 :(得分:3)

在您的声明中

if (x)

{x不是一个布尔表达式,它是一个 Nullable bool ...简而言之,您不能放置不评估为if语句中的布尔表达式

但是,您可以通过指定Lifttrue false来使用,这利用了 Nullable Lifted运算符。例如

if (x == true)
//or
if (x == false)

类似地,提升是导致以下问题起作用的原因。

int? i = null;
if(i > 0) {...}

这也可以通过 Null-Conditional 运算符

看到
if (SomeObj?.Length > 0) 

这里发生的是, Null-Conditional 强制将Length(它是int)解释为 Nullable { {1}}被检查是否为空,并提升到int进行比较

注意 :重新解释时实际生成的IL看起来像这样

int

即使生成的代码违反直觉,对于 Nullable-Types lifting 也是特例,编译器对各种转换和运算符

的处理方式也有所不同

通过在提升的运算符提升转换

上浏览Standard ECMA-334 5th Edition specifications,可以了解更多信息
  

12.4.8解除运营商

     

提升的运算符允许预定义和用户定义的运算符   对非可空值类型进行操作以与可空值一起使用   这些类型的形式。提升的操作员是根据预定义构造的   和满足某些要求的用户定义的运算符,例如   如下所述

答案 1 :(得分:1)

您的对等是错误的。

写作var x = s[0]?.Length > 0;bool x = false相同,而不是bool? x = null

产生的未优化的IL是:

IL_0013:  ldloc.0     // s
IL_0014:  ldc.i4.0    
IL_0015:  ldelem.ref  
IL_0016:  dup         
IL_0017:  brtrue.s    IL_001D
IL_0019:  pop         
IL_001A:  ldc.i4.0    
IL_001B:  br.s        IL_0025
IL_001D:  call        System.Text.StringBuilder.get_Length
IL_0022:  ldc.i4.0    
IL_0023:  cgt         
IL_0025:  stloc.1     // x

brtrue.s为“ s[0]而不是true或非零”时,行null仅分支,因此跳转到比较{{1 }}与.Length-否则,它会到达0分支,该分支只是跳转到将结果设置为br.s的代码。

因此,它等效于false而不是bool x = false

  

我的理解是if语句内的表达式必须是布尔表达式。布尔表达式(我的理解可能是错误的)是计算结果为true或false的表达式。

您的理解正确。

代码在ILSpy中反编译为:

bool? x = null

答案 2 :(得分:-1)

叹息,我相信更多谷歌搜索为我提供了答案! 这里的问题帮助我:Trying to understand ?. (null-conditional) operator in C#

基本上,对于某些运算符(我相信<,>,<=,> =),这些运算符被“提升”以处理空值情况。如果这些二进制运算符中的任何一个操作数为null,它们将自动返回false。

例如

int? x = 5;
int? y = 10;
bool b = x < y; // true

为什么这样做?因为它在语义上等同于:

bool b = (x.HasValue && y.HasValue) ? (x.Value < y.Value) : false;

如果其中一个操作数没有值,则始终返回false。

谢谢!