Null合并,三元或If语句的工作速度更快 [英] Which works faster Null coalesce , Ternary or If Statement

查看:97
本文介绍了Null合并,三元或If语句的工作速度更快的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们使用?运算符,用于根据空值评估表达式,例如:

  string foo = null; 
string bar = woooo;
字符串foobar = foo ??酒吧;
//将foobar评估为woooo

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

  string foo = null; 
string bar = woooo;
if(foo == null)
字符串foobar = woooo;
//将foobar评估为与
上的oooo相同$$$

还有 ?:三元运算符 ...

  string foo = null; 
string bar = woooo;
字符串foobar = foo == null? woooo:null;
//将foobar评估为woooo,与

相同,我知道null合并在语法,但是两者之间编译速度更快,执行速度也更快,为什么?

解决方案

您可能会问错问题。出于效率(尽管可能是次要的考虑),您不会选择使用另一种方法,但是由于实用性。



真的,您应该比较 ?? ?:而不是 if 不同的目的。是的,它们都是某种形式的有条件的善意,但是关键是 ?? ?:计算为一个值,而 if 没有,因此它们通常具有不同的用途。



例如,以下内容代码:

  Console.WriteLine(订单}适用于{1}产品,
orderId,productId? ?每个);

如果书写会比较笨拙:

  if(productId == null)
{
Console.WriteLine(订单{0 }适用于每种产品,
orderId);
}
else
{
Console.WriteLine(订单{0}适用于{1}产品,
orderId,productId);
}

是的,您可以冷凝一个,但是之后变量等。

  if(productId == null)
{
productId = Every;
}

Console.WriteLine(订单{0}适用于{1}产品,
orderId,productId);

因此,实际上,您不应该将两者进行比较,因为它们指向 ?? 如果参数为 null ,则求值,而如果是要执行不同的路径(不是直接产生一个值。



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

  Console.WriteLine(订单{0}适用于{1}产品,
orderId,productId == null? :productId);

两者基本相同(两者均取值)并且不相同



所以,让我们看一下区别。让我们以三种方式编写此代码:

  //方式1与if 
字符串foo =空;
字符串文件夹= foo;

if(文件夹==空)
{
folder = bar;
}

//带有?的方式2:
字符串foo2 = null;
var folder2 = foo2 != null?foo2: bar;

//用?的方式3 ?
字符串foo3 = null;
var folder3 = foo3 ?? 酒吧;

对于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

条件(?:)我们得到以下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

对于空凝聚(??)我们得到这个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

请注意,每个连续的对象如何简单? if 是较大的IL,因为它需要分支逻辑来处理单独的语句。 ?:较小,因为它只是求值(不分支到其他语句),但仍需要加载操作数以与( null )。



?? 是最简单的,因为有一个IL指令,用于比较 null (与加载 null 并进行比较。



SO 所有这些都表示,您在IL方面的差别很小,这可能会或可能不会影响性能。无论如何,这有可能会与程序中的大量工作(数学,数据库,网络等)相比,几乎没有什么主要差异。



因此,我建议选择一个这是可读的,并且只有在通过性能分析发现您当前的方法不足和存在瓶颈时才进行优化。



对我来说,使用?: ?? 的真正原因是当您希望最终结果为val时ue。也就是说,任何时候您都想写:

  if(someCondition)
x = value1;
else
x = value2;

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



然后我再进一步 ?? 说同样的话,您想基于 null -ness为变量赋值



所以 if 对于流量控制非常有用,但是如果您只是返回两个值之一值或根据条件指定两个值之一,我将根据需要使用?: ??



最后请记住,这些内容是如何在幕后实施的(IL及其相关性能)会随版本的每次修订而变化。 .NET Framework(就我撰写本文而言,它们是如此接近,可以忽略不计)。



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



更新



顺便说一句,对于真正的痴迷者,我比较了上面每个代码样本的10,000,000次迭代,这是执行每个代码的总时间。看来 ?? 对我来说是最快的,但这又是所以几乎是无关紧要的...

  10,000,000次迭代:
?:耗时:489毫秒,4.89E-06毫秒/项目。
?花费:458毫秒,4.58E-06毫秒/项目。
如果使用:641毫秒,6.41E-06毫秒/项目。


We use ?? Operator to evaluate expressions against null values, for example:

string foo = null;
string bar = "woooo";
string foobar= foo ?? bar ; 
// Evaluates foobar as woooo

We also used an if statement, which works the same if used with above expression

string foo = null;
string bar = "woooo";
if(foo==null)
   string foobar=   "woooo" ;
// Evaluates foobar as woooo same as above

And also ?: Ternary Operator...

string foo = null;
string bar = "woooo";    
string foobar= foo==null ? "woooo" : null ;
// Evaluates foobar as woooo same as above

I know that null coalescing is precise in syntax, but which one is compiled faster among both and performs more faster and why?

解决方案

You may be asking the wrong question. You don't choose to use one over the other primarily due to efficiency (though it may be a secondary concern), but due to utility.

Really you should compare ?? to ?: and not to if as they have different purposes. Yes, they are all some form of "conditional" goodness, but the key is that both ?? and ?: evaluate to a value, whereas if does not, thus they often have different uses.

For example, the following code:

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

Would be clunkier to write with an 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);
}

Yes, you could condense to one, but then you'd have a temp variable, etc:

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

Console.WriteLine("The order {0} is for {1} product",
    orderId, productId);

Thus really, you shouldn't compare the two, because they point of the ?? is to evaluate to a value if the argument is null, whereas the point of if is to execute a different path (not directly resulting in a value.

So, a better question may be, why not this instead:

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

Which is much the same (both evaluate to a value) and are not as much for flow control.

So, let's look at the difference. Let's write this code three ways:

// 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";

For the IF, we get the following 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     

For the conditional (? :) we get the following 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   

For the null-coallescing (??) we get this 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    

Notice how each successive one is simpler? The if is larger IL because it needs branching logic to handle the separate statements. The ?: is smaller because it simply evaluates to a value (not branching to other statements) but still needs to load the operand to compare to (null).

The ?? is the simplest of all, because there is an IL instruction for comparing to null (vs loading null and comparing to it.

SO all of this said, you're talking a very small difference in terms of IL, which may or may not affect performance. Regardless, chances are this will have very little major difference compared to more intensive work in the program (math, database, network, etc.).

Thus, I would suggest choose the one that is the most readable, and only optimize if you find through profiling that your current method is inadequate and a bottleneck.

To me, the real reason to use ?: or ?? is when you want the end result to be a value. That is, anytime you'd be tempted to write:

if (someCondition)
    x = value1;
else 
    x = value2;

Then I'd use the conditional (?:) because that is what it is a great shorthand for. x gets one or the other value based on this condition...

Then I'd go one further with ?? and say the same is true, you want to assign a value to a variable based on the null-ness of an identiifer.

So if is great for flow-control, but if you are just returning one of two values or assigning one of two values based on a condition, I'd use ?: or ?? as appropriate.

Finally keep in mind how these things are implemented under the covers (IL and the associated performance) are subject to change with each revision of the .NET Framework (as of me writing this right now they are all so close to be negligible).

Thus, what may be faster today may not be faster tomorrow. So again, I'd just say go with the one that fits best and you find most readable.

UPDATE

Incidentally, for the truly obsessed, I compared 10,000,000 iterations of each code swatch above, and here's the total time to execute each. Looks like ?? is fastest for me, but again these are so close to be almost inconsequential...

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.

这篇关于Null合并,三元或If语句的工作速度更快的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆