2

次のようなローカル変数のない単純なメソッドの場合

public static int Test1(short i, long j)
{
    j = i + j;

    switch (j)
    {
    case 1:
        j = 2;
        break;
    default:
        j = 11;
        break;
    }

    return j;
}

MethodInfo.GetMethodBody().LocalVariables.Count = 2 のカウント なぜ? 別の switch ステートメントを追加すると、カウントが 3 になります なぜ?

public static int Test1(short i, long j)
{
    j = i + j;

    switch (j)
    {
    case 1:
        j = 2;
        break;
    default:
        j = 11;
        break;
    }

    switch (i)
    {
    case 1:
        j = 2;
        break;
    default:
        j = 11;
        break;
    }

    return j;
}

ローカル変数は定義されていません。では、なぜ 2 と 3 なのか。また、j を指定した別の switch ステートメントがカウントを 2 に保つ場合。

4

1 に答える 1

2

C# コンパイラが C# ソース コードにないローカル変数を生成するという事実は、当然のことだと思います。これは、IL スタックが常に一時的な値を格納するのに最適な場所であるとは限らないためです。アクセスできるのはトップに限られるからです。

これは特にデバッグ ビルドに当てはまります。これは、パフォーマンスやメモリ フットプリントではなく、デバッグ用に最適化されているためです。これらのローカルがデバッガーをどのように支援するのか、またはまったく支援するのかどうかはわかりませんが、彼らの主張は正しいと思います。

具体的には、 jmh_gr が指摘したように、暗黙的に にキャストできないため、メソッドは実際にはコンパイルされませlongint。の型をjtoに変更するとint、デバッグ構成を使用すると次のようなコードが生成されます (リフレクターを使用して逆コンパイルし、最適化を無効にします)。

public static int Test1(short i, int j)
{
    int CS$1$0000;
    int CS$4$0001;
    j = i + j;
    CS$4$0001 = j;
    if (CS$4$0001 != 1)
    {
        goto Label_0013;
    }
    j = 2;
    goto Label_0019;
Label_0013:
    j = 11;
Label_0019:
    CS$1$0000 = j;
Label_001D:
    return CS$1$0000;
}

ご覧のとおり、このメソッドには実際には 2 つのローカルがあり、両方が使用されています。リリース構成を使用する場合、生成された IL にはローカル変数が 1 つしかなく、次のようになります。

public static int Test1(short i, int j)
{
    int CS$0$0000;
    j = i + j;
    CS$0$0000 = j;
    if (CS$0$0000 != 1)
    {
        goto Label_0010;
    }
    j = 2;
    goto Label_0014;
Label_0010:
    j = 11;
Label_0014:
    return j;
}

ローカルは必要ないように見えますが、それには正当な理由があるかもしれません。そしてもちろん、パフォーマンスにとって本当に重要なのは、IL コードではなく、JIT でコンパイルされたアセンブリです。

于 2012-03-17T04:31:13.240 に答える