我们使用?? Operator根据空值对表达式求值,例如:
string foo = null;
string bar = "woooo";
string foobar= foo ?? bar ;
// Evaluates foobar as woooo我们还使用了if语句,如果与上面的表达式一起使用,它的工作方式相同
string foo = null;
string bar = "woooo";
if(foo==null)
string foobar= "woooo" ;
// Evaluates foobar as woooo same as above还有?: Ternary Operator..。
string foo = null;
string bar = "woooo";
string foobar= foo==null ? "woooo" : null ;
// Evaluates foobar as woooo same as above我知道null合并在语法上是精确的,但是在这两个中哪一个编译得更快,执行得更快,为什么?
发布于 2012-11-15 03:15:26
你可能问错了问题。您不会选择使用一个而不是另一个,主要是因为效率(尽管这可能是次要的问题),而是出于实用性。
实际上,您应该将??与?:进行比较,而不是将其与if进行比较,因为它们有不同的目的。是的,它们都是某种形式的“条件”好,但关键是??和?:都求值,而if不求值,因此它们通常有不同的用途。
例如,以下代码:
Console.WriteLine("The order} is for {1} product",
orderId, productId ?? "every");使用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);
}是的,你可以压缩成一个,但之后你会有一个临时变量,等等:
if (productId == null)
{
productId = "every";
}
Console.WriteLine("The order {0} is for {1} product",
orderId, productId);因此,您真的不应该比较这两者,因为如果参数为null,则??的要点是计算一个值,而if的要点是执行不同的路径(而不是直接产生一个值。
因此,一个更好的问题可能是,为什么不这样做:
Console.WriteLine("The order {0} is for {1} product",
orderId, productId == null ? "every" : productId);这几乎是相同的(两者的计算结果都是一个值),但对于流控制来说就不一样了。
那么,让我们来看看它们之间的区别。让我们以三种方式编写这段代码:
// 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";对于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 对于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 注意到每个连续的是如何变得更简单的吗?if是较大的IL,因为它需要分支逻辑来处理单独的语句。?:较小,因为它只是计算为一个值(而不是分支到其他语句),但仍然需要加载操作数以与(null)进行比较。
??是所有代码中最简单的,因为有一个IL指令用于与null进行比较(与加载null并进行比较。
,SO,所有这些都说,你说的是IL方面的很小的差异,这可能会也可能不会影响性能。无论如何,与程序中更密集的工作(数学、数据库、网络等)相比,这可能会使有很小的主要区别。
因此,我建议选择可读性最好的方法,只有在通过分析发现当前方法不足和瓶颈时才进行优化。
对我来说,使用?:或??的真正原因是您希望最终结果是一个值。也就是说,任何时候你想写:
if (someCondition)
x = value1;
else
x = value2;然后我会使用条件(?:),因为这是一个很好的简写。x根据此条件获取一个或另一个值...
然后我用??更进一步,假设这也是真的,你想要根据一个身份的null-ness给一个变量赋值。
因此,if对于流量控制非常有用,但如果只是返回两个值中的一个,或者根据条件分配两个值中的一个,我会适当地使用?:或??。
最后,记住这些东西是如何在幕后实现的(IL和相关的性能)会随着.NET框架的每次修订而变化(在我写这篇文章的时候,它们都是如此接近,以至于可以忽略不计)。
因此,今天可能更快的东西明天可能不会更快。所以我再说一遍,我只想用最适合的,你会发现最具可读性的。
更新
顺便说一句,对于真正着迷的人,我比较了上面每个代码样本的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.https://stackoverflow.com/questions/13385503
复制相似问题