4

これは私がやりたいことです:

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));

より簡潔なコードの場合。私の質問は、コンパイラが割り当てを最適化して、ブール式が同じであることを確認し、その値を 2 番目のボタンに割り当てるか、または毎回値を計算するかということです。

注: これは些細な例であり、スピードアップ/スローダウンは取るに足らないほど小さいことは理解していますが、コンパイラの最適化をよりよく理解するのに役立ちます。

編集: 2 番目のオプションが最適化される可能性があると考えた理由は次のとおりです。

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));
    }
}

これにより、10 億回の操作で約 8 ~ 9 秒の差が生じました (2 番目のオプションの方が高速です)。ただし、「有効」ブール値を追加すると、2 番目の操作が遅くなりました。

4

3 に答える 3

7

いいえ、コンパイラがそれを最適化するとは思いません。JITがそれを最適化できる可能性はありますが(よ​​り多くの情報があるため)、C#コンパイラーには期待できません。

コンパイラは、またはSomeButton.Enabledの値を変更する副作用があるかどうかをどのように知ることができますか?ABooleanBBooleanCBoolean

編集:これの検証... C#コンパイラに絶対的なチャンスを与えましょう:

class Test
{
    static void Main()
    {
        Foo(true, false, true);
    }

    static void Foo(bool x, bool y, bool z)
    {
        A = x || (y && z);
        B = x || (y && z);
    }

    static bool A { get; set; }
    static bool B { get; set; }
}

コンパイル:

csc /o+ /debug- Test.cs

FooILDASM 経由のコード:

.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

ご覧のとおり、式は実際に両方のケースで評価されます。

于 2012-06-01T15:04:58.483 に答える
4

私の質問は、コンパイラが割り当てを最適化して、ブール式が同じであることを確認し、その値を 2 番目のボタンに割り当てるか、または毎回値を計算するかです。

毎回値を計算します。

これがマルチスレッド アプリケーションだったらどうなるでしょうか。他のスレッドがそれを変更する可能性があります。

定数変数でない場合は、変更できます。

最適化するには、次のことができます

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

この場合、一度計算され、値が最初に割り当てられAnotherButtonますSomeButton。代入では右から左に覚えておいてください。

于 2012-06-01T15:04:31.217 に答える
2

いいえ、私の経験ではコンパイラは最適化しませんが、次のことができます。

SomeButton.Enabled = AnotherButton.Enabled = (ABoolean || (BBoolean && CBoolean));
于 2012-06-01T15:11:26.993 に答える