C# 编译器会优化布尔赋值吗?

C# 编译器会优化布尔赋值吗?,c#,compiler-optimization,C#,Compiler Optimization,这就是我想做的: if(ABoolean || (BBoolean && CBoolean)) { SomeButton.Enabled = true; AnotherButton.Enabled = true; } else { SomeButton.Enabled = false; AnotherButton.Enabled = false; } 我可以切换到: SomeButton.Enabled = (ABoolean || (BBoo

这就是我想做的:

if(ABoolean || (BBoolean && CBoolean))
{
    SomeButton.Enabled = true;
    AnotherButton.Enabled = true;
}
else 
{
    SomeButton.Enabled = false;
    AnotherButton.Enabled = false;
}
我可以切换到:

SomeButton.Enabled = (ABoolean || (BBoolean && CBoolean));
AnotherButton.Enabled = (ABoolean || (BBoolean && CBoolean));
获取更简洁的代码。我的问题是,编译器是否优化赋值,使其看到布尔表达式是相同的,并为第二个按钮赋值,还是每次都计算值

注意:我知道这是一个很小的例子,加速/减速将是微不足道的,但它将有助于我更好地理解编译器优化

编辑:以下是我认为第二个选项可能会优化的原因:

class Program
{
    static bool ABoolean = true, BBoolean = true, CBoolean = false;
    static bool AEnable, BEnable;


    static void Main(string[] args)
    {
        Stopwatch sw = new Stopwatch();
        sw.Start();
        for (int i = 0; i < 1000000000; i++)
        {
            Operation1();
        }
        sw.Stop();
        Console.WriteLine(sw.ElapsedMilliseconds);

        Stopwatch sw1 = new Stopwatch();
        sw1.Start();
        for (int i = 0; i < 1000000000; i++)
        {
            Operation2();
        }
        sw1.Stop();
        Console.WriteLine(sw1.ElapsedMilliseconds);
        Console.Read();
    }

    static void Operation1()
    {
        if (ABoolean || (BBoolean && CBoolean))
        {
            AEnable = true;
            BEnable = true;
        }
        else
        {
            AEnable = false;
            BEnable = false;
        }
    }

    static void Operation2()
    {
        AEnable = (ABoolean || (BBoolean && CBoolean));
        BEnable = (ABoolean || (BBoolean && CBoolean));
    }
}
类程序
{
静态bool-ABoolean=true,BBoolean=true,CBoolean=false;
静态bool AEnable,BEnable;
静态void Main(字符串[]参数)
{
秒表sw=新秒表();
sw.Start();
对于(int i=0;i<100000000;i++)
{
操作1();
}
sw.Stop();
控制台写入线(软件延迟毫秒);
秒表sw1=新秒表();
sw1.Start();
对于(int i=0;i<100000000;i++)
{
操作2();
}
sw1.Stop();
Console.WriteLine(sw1.ElapsedMilliseconds);
Console.Read();
}
静态无效操作1()
{
if(ABoolean | |(BBoolean&CBoolean))
{
AEnable=正确;
可弯曲=正确;
}
其他的
{
AEnable=false;
可弯曲=错误;
}
}
静态无效操作2()
{
AEnable=(ABoolean | |(BBoolean&CBoolean));
BEnable=(ABoolean | |(BBoolean和CBoolean));
}
}
这导致在10亿次操作中产生约8-9秒的差异(第二个选项运行得更快)。然而,当我在中添加更多的“Enable”布尔值时,第二个操作变得更慢

我的问题是,编译器是否优化赋值,使其看到布尔表达式是相同的,并为第二个按钮赋值,还是每次都计算值

它将每次计算该值

如果这是一个多线程应用程序呢。其他线程可能会更改它

如果它们不是常量变量,则可以更改它们

为了优化您可以做的事情

SomeButton.Enabled = AnotherButton.Enabled = (ABoolean || (BBoolean && CBoolean));
在这种情况下,它将计算一次,并首先将值分配给另一个按钮,然后再分配给另一个按钮。记住它在赋值中是从右向左的。

不,我不希望编译器优化它。JIT可能会对此进行优化(因为它有更多的信息),但我不希望C#编译器会这样做

编译器如何知道
SomeButton.Enabled
是否会产生一些副作用,从而改变
ABoolean
BBoolean
CBoolean
的值

编辑:验证此。。。让我们给C#编译器最大的机会:

编译时使用:

csc /o+ /debug- Test.cs
通过ILDASM为Foo编码:

.method private hidebysig static void  Foo(bool x,
                                           bool y,
                                           bool z) cil managed
{
  // Code size       37 (0x25)
  .maxstack  8
  IL_0000:  ldarg.0
  IL_0001:  brtrue.s   IL_000c
  IL_0003:  ldarg.1
  IL_0004:  brfalse.s  IL_0009
  IL_0006:  ldarg.2
  IL_0007:  br.s       IL_000d
  IL_0009:  ldc.i4.0
  IL_000a:  br.s       IL_000d
  IL_000c:  ldc.i4.1
  IL_000d:  call       void Test::set_A(bool)
  IL_0012:  ldarg.0
  IL_0013:  brtrue.s   IL_001e
  IL_0015:  ldarg.1
  IL_0016:  brfalse.s  IL_001b
  IL_0018:  ldarg.2
  IL_0019:  br.s       IL_001f
  IL_001b:  ldc.i4.0
  IL_001c:  br.s       IL_001f
  IL_001e:  ldc.i4.1
  IL_001f:  call       void Test::set_B(bool)
  IL_0024:  ret
} // end of method Test::Foo

如您所见,表达式在这两种情况下都会进行计算。

不,根据我的经验,编译器不会对其进行优化,但是,您可以:

SomeButton.Enabled = AnotherButton.Enabled = (ABoolean || (BBoolean && CBoolean));

正确的。因为这是两个独立的语句,涉及的变量不是常量。因此编译器不能在这里假设任何东西。变量可能在这两个语句之间发生了变化,特别是当您的应用程序是多线程的时候。现在您只需要从其他人的答案中获取细节。真是好笑。但我不确定你发布的内容是否真的是优化。布尔运算速度非常快。我认为引用属性的
get
访问器通常与调用内联方法具有相同的开销。因此,这很容易比原始代码慢。虽然我们谈论的是纳秒,但仍然是。@SteveWortham:是的,我承认我复制了它。但是不是从某人的答案而是从我的大脑。实际上,
get
访问器不会被引用,因为赋值的返回值就是被赋值的值。因此,布尔表达式将被计算一次,然后沿着链返回。如果分配链中有不同的类型,可能会产生一些微妙的影响,但这不是问题所在。@SteveCzetty-我运行了另一个测试,您是对的,从未调用
get
访问器。但是我仍然不知道为什么速度会这么慢。顺便说一下:第三种方法是通过变量赋值:
var enabled=(ABoolean | | |(BBoolean&&CBoolean))
,然后使用该变量设置
.enabled
属性。感谢您的回答,我感到困惑,因为我实际上对这两个选项进行了计时,而第二个选项的结果要快得多。我假设这是由于if/else条款的开销造成的。因此,在第二种情况下,布尔运算的数量应该会出现一个无法返回的点,这会导致时间变慢,对吧?@NominSim:我不希望任何一种版本的结果都会显著加快。我怀疑你的诊断:)但是,真的,这对你整体来说可能有点重要吗?远远超过10亿次操作,差异约为8秒(~19对~11)…我认为重要是主观的,当我再添加5个布尔赋值时,第二个选项会变慢。绝对没有什么意义,我只是在解释我最初是如何得出结论的,即它可能会优化第二个版本。@NominSim:这听起来确实很有趣,但很容易破坏微优化测试;特别是,你可以很容易地发现一个版本是内联的,另一个版本不是,但在更大的方法中不会产生影响。我在我的OP中编辑了测试代码,我不确定秒表是否是计时这类事情的最佳方式……你介意看一下它,看看它是否可行吗
SomeButton.Enabled = AnotherButton.Enabled = (ABoolean || (BBoolean && CBoolean));