C# 编译器的优化程度



这段代码的IL代码(用 https://dotnetfiddle.net 生成):

public class Program
{
    public static void Main()
    {
        int i = 10;
        if (i < 4)
            Console.WriteLine("Hello World");
    }
}

包含ldstr"Hello World"。

编译器不应该知道 Console.WriteLine 永远不会被执行吗?

此的 IL 代码:

public class Program
{
    public static void Main()
    {
        if (10 < 4)
            Console.WriteLine("Hello World");
    }
}

不包含 ldstr 命令。

现在我很困惑....NET编译器真的那么愚蠢吗?两个示例的 C#/IL 代码执行完全相同的操作:什么都没有。但是第一个示例的 IL 代码大于另一个示例。一个好的编译器不应该只调用构造函数而不做任何事情吗..?

编辑:

是的,我已经读过这篇文章,但我不是在谈论其他生成的当地人。

如果i是属性或公共变量,则可以从另一个线程修改它。但是i只存在于 Main()...

这是代码段的 x64 反汇编:

00007FF7C6083E0E  add         byte ptr [rax],al  
--- C:DevTempTestConsoleAppConsoleAppProgram.cs --------------------------
            int i = 10;
00007FF7C6083E10  ret  
--- No source file -------------------------------------------------------------

这意味着,JIT 执行了死代码消除(ret = 返回Main函数只是立即退出)。

编译器仅执行一些基本优化,但大部分优化留给 JIT,以针对其运行的平台进行优化。

虽然我同意编译器在这种情况下当然可以执行此优化,因为它与平台无关。

在我看来,编译器的行为符合预期。编译器通常只计算常量和常量表达式,因为它们的值在编译时是已知的。示例中的变量"i"和表达式"i <4"在运行时计算,这就是编译器在这种情况下不优化代码的原因。

我也认为这不应该是调试器的责任。尽管在您的样本中一切都很明显,但在计算值时,每条线都显示出累积影响,这是一个巨大的工作量,请将其视为计算可用的国际象棋移动总量。(国际象棋中可用的步数比宇宙中的全明星多出数十亿步。

相关内容

  • 没有找到相关文章

最新更新