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)
它们应该编译为相同的IL,从而执行相同的操作.
即使他们没有,性能差异也可以忽略不计.除非我描述我的申请并且看到这些陈述需要花费大量时间,否则我甚至不会考虑这样做.
始终使用最清晰的语法,除非您能证明它导致性能问题,而不是之前.