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 WHY?

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 指出的那样,您的方法实际上不会编译,因为您不能隐式long转换为int. 如果我将类型更改jint,它会在使用调试配置时生成类似这样的代码(使用反射器进行反编译,禁用优化):

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

所以,你看,这个方法实际上有两个局部变量,并且都被使用了。使用发布配置时,生成的 IL 只有一个局部变量,如下所示:

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

看起来本地不应该是必要的,但也许有一个很好的理由。当然,对性能真正重要的是 JIT 编译的程序集,而不是 IL 代码。

于 2012-03-17T04:31:13.240 回答