哪个工作更快Null coalesce,Ternary或If Statement

May*_*hak 6 .net c# null-coalescing-operator

我们用?? 运算符根据空值计算表达式,例如:

string foo = null;
string bar = "woooo";
string foobar= foo ?? bar ; 
// Evaluates foobar as woooo
Run Code Online (Sandbox Code Playgroud)

我们还使用了一个if语句,如果与上面的表达式一起使用,它的作用相同

string foo = null;
string bar = "woooo";
if(foo==null)
   string foobar=   "woooo" ;
// Evaluates foobar as woooo same as above
Run Code Online (Sandbox Code Playgroud)

还有?:三元运营商 ......

string foo = null;
string bar = "woooo";    
string foobar= foo==null ? "woooo" : null ;
// Evaluates foobar as woooo same as above
Run Code Online (Sandbox Code Playgroud)

我知道空合并在语法上是精确的,但哪一个在两者之间编译得更快,执行速度更快,为什么?

Jam*_*are 20

你可能会问错误的问题.您不会选择使用一个而不是主要由于效率(尽管它可能是次要问题),但由于实用性.

真的是你应该比较???:,而不是if因为他们有不同的用途.是的,他们都是某种形式的"有条件的"善良的,但关键是,无论???:评估的值,而if没有,因此,他们往往有不同的用途.

例如,以下代码:

Console.WriteLine("The order} is for {1} product",
    orderId, productId ?? "every");
Run Code Online (Sandbox Code Playgroud)

用以下内容写出来会更笨拙if:

if (productId == null)
{
    Console.WriteLine("The order {0} is for every product",
        orderId);
}
else
{
    Console.WriteLine("The order {0} is for {1} product",
        orderId, productId);
}
Run Code Online (Sandbox Code Playgroud)

是的,你可以压缩到一个,但是你有一个临时变量等:

if (productId == null)
{
    productId = "every";
}

Console.WriteLine("The order {0} is for {1} product",
    orderId, productId);
Run Code Online (Sandbox Code Playgroud)

因此,实际上,你不应该比较两者,因为??如果参数是null,它们指向的是评估值,而要点if是执行不同的路径(不直接产生值).

所以,一个更好的问题可能是,为什么不这样做:

Console.WriteLine("The order {0} is for {1} product",
    orderId, productId == null ? "every" : productId);
Run Code Online (Sandbox Code Playgroud)

这是相同的(都评估为一个值),并没有多少流量控制.

那么,让我们看看差异.让我们用三种方式编写这段代码:

// Way 1 with if
string foo = null;
string folder = foo;

if (folder == null)
{
    folder = "bar";
}

// Way 2 with ? :
string foo2 = null;
var folder2 = foo2 != null ? foo2 : "bar";

// Way 3 with ??
string foo3 = null;
var folder3 = foo3 ?? "bar";
Run Code Online (Sandbox Code Playgroud)

对于IF,我们得到以下IL:

IL_0001:  ldnull      
IL_0002:  stloc.0     
IL_0003:  ldloc.0     
IL_0004:  ldnull      
IL_0005:  ceq         
IL_0007:  ldc.i4.0    
IL_0008:  ceq         
IL_000A:  stloc.1     
IL_000B:  ldloc.1     
IL_000C:  brtrue.s    IL_0016
IL_000E:  nop         
IL_000F:  ldstr       "bar"
IL_0014:  stloc.0     
Run Code Online (Sandbox Code Playgroud)

对于条件(?:),我们得到以下IL:

IL_0001:  ldnull      
IL_0002:  stloc.0     
IL_0003:  ldloc.0     
IL_0004:  brtrue.s    IL_000D
IL_0006:  ldstr       "bar"
IL_000B:  br.s        IL_000E
IL_000D:  ldloc.0     
IL_000E:  nop         
IL_000F:  stloc.1   
Run Code Online (Sandbox Code Playgroud)

对于null-coallescing(??),我们得到这个IL:

IL_0001:  ldnull      
IL_0002:  stloc.0     
IL_0003:  ldloc.0     
IL_0004:  dup         
IL_0005:  brtrue.s    IL_000D
IL_0007:  pop         
IL_0008:  ldstr       "bar"
IL_000D:  stloc.1    
Run Code Online (Sandbox Code Playgroud)

请注意每个连续的如何更简单?的if是IL较大,因为它需要分支逻辑来处理单独的语句.该?:较小,因为它只是计算的值(不转移到其它语句),但仍需要加载操作数来比较(null).

??是最简单的,因为有一个用于比较的IL指令null(vs加载null和比较它.

SO这一切说,你说的IL而言,这可能会或可能不会影响性能非常小的差异.无论如何,没准这将有非常相比,程序更加深入细致的工作(数学,数据库,网络等)的小主要区别.

因此,我建议选择最具可读性的那个,并且只有在通过分析找出当前方法不充分且瓶颈时才进行优化.

对我来说,使用的真正原因是,?:或者??当你希望最终结果成为价值时.也就是说,任何时候你都想写作:

if (someCondition)
    x = value1;
else 
    x = value2;
Run Code Online (Sandbox Code Playgroud)

然后我会使用conditional(?:)因为这是一个很好的简写. x根据这个条件得到一个或另一个值...

然后我再继续??说并且说同样如此,你想根据null一个标识符的一致性为变量赋值.

因此if对于流量控制非常有用,但如果您只是返回两个值中的一个或根据条件分配两个值中的一个,我会使用?:??酌情使用.

最后请记住,这些内容如何在幕后实现(IL和相关性能)随.NET Framework的每个版本而变化(从我现在开始写这些内容它们都非常接近可以忽略不计).

因此,今天可能更快的可能明天不会更快.再说一遍,我只想说最合适的一个,你发现最可读.

UPDATE

顺便说一下,对于真正的痴迷者,我比较了上面每个代码样本的10,000,000次迭代,这是执行每个代码样本的总时间.看起来??对我来说速度最快,但这些几乎是如此接近几乎无关紧要......

10,000,000 iterations of:
?: took: 489 ms, 4.89E-06 ms/item.
?? took: 458 ms, 4.58E-06 ms/item.
if took: 641 ms, 6.41E-06 ms/item.
Run Code Online (Sandbox Code Playgroud)


Jus*_*ner 5

它们应该编译为相同的IL,从而执行相同的操作.

即使他们没有,性能差异也可以忽略不计.除非我描述我的申请并且看到这些陈述需要花费大量时间,否则我甚至不会考虑这样做.

始终使用最清晰的语法,除非您能证明它导致性能问题,而不是之前.

  • @JamesMichaelHare - 真的吗?这令人惊讶.不幸的是,我没有在我面前有什么东西我可以看看...有什么区别? (2认同)