为什么 IF 和条件运算符之间的 IL 存在如此大的差异?

发布于 2024-12-02 18:28:43 字数 1516 浏览 1 评论 0原文

C# 有一个 条件运算符 和 IF 语句,我怀疑条件运算符只是语法糖。所以在编译时它会有一个与 IF 操作相同的操作。

然而它们没有(见下文),它们确实有不同的 IL。尝试着理解它,我的假设是,这是条件运算符获得的性能优化,因为它的范围有限。

想知道我的假设是否正确,也许还有更多内容?

另外,在 IF 的 IL 中,还有一些围绕 int 值的检查(L_000c、L_000d、L_000f),我无法弄清楚其含义。这让我认为这是一个更强大的解决方案,但由于 IF 范围更大而以性能为代价。


Code for IF

var result = "";
if (Environment.Is64BitOperatingSystem)
{
    result = "Yes";
}
else
{
    result = "No";
}
Console.WriteLine(result);

条件运算符的代码(我意识到差异,但无论我如何更改它 - 分配给变量等......它几乎没有什么区别)

Console.WriteLine("Is the OS x64? {0}", Environment.Is64BitOperatingSystem ? "Yes" : "No");

IL for IF

L_0001: ldstr ""
L_0006: stloc.0 
L_0007: call bool [mscorlib]System.Environment::get_Is64BitOperatingSystem()
L_000c: ldc.i4.0 
L_000d: ceq 
L_000f: stloc.2 
L_0010: ldloc.2 
L_0011: brtrue.s L_001d
L_0013: nop 
L_0014: ldstr "Yes"
L_0019: stloc.0 
L_001a: nop 
L_001b: br.s L_0025
L_001d: nop 
L_001e: ldstr "No"
L_0023: stloc.0 
L_0024: nop 
L_0025: ldloc.0 
L_0026: call void [mscorlib]System.Console::WriteLine(string)

IL for Conditional

L_002c: ldstr "Is the OS x64? {0}"
L_0031: call bool [mscorlib]System.Environment::get_Is64BitOperatingSystem()
L_0036: brtrue.s L_003f
L_0038: ldstr "No"
L_003d: br.s L_0044
L_003f: ldstr "Yes"
L_0044: call void [mscorlib]System.Console::WriteLine(string, object)

C# has a conditional operator and IF statements and I suspected that the conditional operator would be just syntactic sugar. So at compile time it would have a the same as an IF operation.

However they do not (see below), they do have different IL. Trying to wrap my head around it and the assumption I have is that this is a performance optimisation that the conditional operator gets because it's limited scope.

Would like to know if my assumption is correct or not and maybe if there is more to this?

Also in the IF's IL there is some checks (L_000c, L_000d, L_000f) around int values which I can't figure out the meaning. This is what has lead me to think this is a more robust solution, at the cost of performance because of IF greater scope.


Code for IF

var result = "";
if (Environment.Is64BitOperatingSystem)
{
    result = "Yes";
}
else
{
    result = "No";
}
Console.WriteLine(result);

Code for conditional operator (I realise differences, but no matter how I change it - assign to variable etc... it makes very little difference)

Console.WriteLine("Is the OS x64? {0}", Environment.Is64BitOperatingSystem ? "Yes" : "No");

IL for IF

L_0001: ldstr ""
L_0006: stloc.0 
L_0007: call bool [mscorlib]System.Environment::get_Is64BitOperatingSystem()
L_000c: ldc.i4.0 
L_000d: ceq 
L_000f: stloc.2 
L_0010: ldloc.2 
L_0011: brtrue.s L_001d
L_0013: nop 
L_0014: ldstr "Yes"
L_0019: stloc.0 
L_001a: nop 
L_001b: br.s L_0025
L_001d: nop 
L_001e: ldstr "No"
L_0023: stloc.0 
L_0024: nop 
L_0025: ldloc.0 
L_0026: call void [mscorlib]System.Console::WriteLine(string)

IL for Conditional

L_002c: ldstr "Is the OS x64? {0}"
L_0031: call bool [mscorlib]System.Environment::get_Is64BitOperatingSystem()
L_0036: brtrue.s L_003f
L_0038: ldstr "No"
L_003d: br.s L_0044
L_003f: ldstr "Yes"
L_0044: call void [mscorlib]System.Console::WriteLine(string, object)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

阳光下的泡沫是彩色的 2024-12-09 18:28:43

如果

IL_0000:  call       bool [mscorlib]System.Environment::get_Is64BitOperatingSystem()
IL_0005:  brfalse.s  IL_000f
IL_0007:  ldstr      "Yes"
IL_000c:  stloc.0                  // <------ Difference 1
IL_000d:  br.s       IL_0015
IL_000f:  ldstr      "No"
IL_0014:  stloc.0
IL_0015:  ldloc.0
IL_0016:  call       void [mscorlib]System.Console::WriteLine(string)

? (三元运算符

IL_001b:  call       bool [mscorlib]System.Environment::get_Is64BitOperatingSystem()
IL_0020:  brtrue.s   IL_0029
IL_0022:  ldstr      "No"          // <------ Difference 2
IL_0027:  br.s       IL_002e
IL_0029:  ldstr      "Yes"
IL_002e:  stloc.0
IL_002f:  ldloc.0
IL_0030:  call       void [mscorlib]System.Console::WriteLine(string)

在发布模式下两者的代码几乎相同。 if 添加了第二个 stdloc.0,编译器未对其进行优化。另一个区别是 truefalse 是相反的。

(所以我知道我应该始终启动 WinMerge!)

这将是一个有趣的问题。为什么它们是倒置的?有什么逻辑吗?

if

IL_0000:  call       bool [mscorlib]System.Environment::get_Is64BitOperatingSystem()
IL_0005:  brfalse.s  IL_000f
IL_0007:  ldstr      "Yes"
IL_000c:  stloc.0                  // <------ Difference 1
IL_000d:  br.s       IL_0015
IL_000f:  ldstr      "No"
IL_0014:  stloc.0
IL_0015:  ldloc.0
IL_0016:  call       void [mscorlib]System.Console::WriteLine(string)

? (ternary operator)

IL_001b:  call       bool [mscorlib]System.Environment::get_Is64BitOperatingSystem()
IL_0020:  brtrue.s   IL_0029
IL_0022:  ldstr      "No"          // <------ Difference 2
IL_0027:  br.s       IL_002e
IL_0029:  ldstr      "Yes"
IL_002e:  stloc.0
IL_002f:  ldloc.0
IL_0030:  call       void [mscorlib]System.Console::WriteLine(string)

(nearly)same code for both in release mode. The if adds a second stdloc.0 that isn't optimized away by the compiler. And the other difference is that the true and false are inverted.

(so I learn that I should ALWAYS fire up WinMerge!)

And THIS would be an interesting question. Why are they inverted? Is there any logic?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文