C#中的编译器优化if/else

3

我对编译器以及.Net如何优化生成的机器代码了解不多,但我想了解以下情况:

    class AnyClass
    {
        public bool anyFlag;
        AnyClass()
        {
            anyFlag = true;
        }

        public void Action()        
        {
            if(anyFlag)
                 //Perform Certain Actions
        }
    }

anyFlag在程序的范围内不会改变。编译器会为Action方法生成MIL/机器代码吗?如果是,其中是否会有if检查?


我猜你的意思是私有布尔型变量 anyFlag; - vc 74
一个单独的if语句对你来说为什么那么重要? - svick
1
我更多地从理解的角度提出了这个问题。我猜最终它确实很重要 :) - Aziz
2个回答

7
在您的情况下,编译器不会过滤if语句,因为您的anyFlag是公共的(因此可以从多个位置更改),并且由于该值仅在构造函数中设置,编译器在运行时也不知道此值。
以下代码可以实现您想要的功能:
static void MyFunc()
{
    const bool flag = true;

    string s = null;
    if (flag)
    {
        s = "a";
    }
    else
    {
        s = "b";
    }
}

如果您在Visual Studio中插入此代码,您将会看到生成的警告,指出s="b";将永远不会被执行,并且该代码将被优化掉。

1

是的,编译器会生成IL代码。由于您稍后可以使用反射或Emit调用该方法或更改anyFlag的值,因此它将保留。您可以通过使用Visual Studio附带的ildasm反汇编生成的可执行文件来证明这一点。


3
就性能而言,IL并不重要,JIT生成的本机代码才是关键。 - svick
当然可以,但由于JIT编译器的优化是一个黑盒子,并没有对此进行规定。你只能相信它正在做它的工作。更重要的是生成IL并且开发人员能够在需要时访问代码。 - Polynomial
@Polynomial “你可以通过使用ildasm反汇编生成的可执行文件来展示这一点”,只需自己尝试上面的代码(带有const bool)。 - L.B
@Polynomial,你说什么没有规范?CLI规范说明了每个IL指令应该如何行动,尽管它没有明确指定应使用哪些汇编指令。同样,C#规范说明了每个C#结构应该如何行动,但并不确定要使用哪些IL指令。(它甚至没有说你必须使用IL!) - svick
@L.B. 如果它是 const bool,它将被省略。但他的代码并没有声明 const bool - Polynomial
@svick - 你误解了。当然,每个指令的行为都在严格规范(ECMA-334)下定义。我想说的是,没有规范说明JIT编译器如何将IL优化为本机代码。在这方面,它是完全的黑盒子工作。你无法保证JIT编译器是否会读取IL并缓存本机指令,或者跳过完全不读取IL,因为它从未被调用。 - Polynomial

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接