对于没有局部变量的简单方法,如下所示
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。
答案 0 :(得分:2)
我认为C#编译器生成不在C#源代码中的局部变量这一事实是可以预期的。那是因为IL堆栈并不总是存储一些临时值的好地方,因为你只能访问它的顶层。
这尤其适用于调试版本,因为它们针对调试进行了优化,而不是针对性能或内存占用。我不知道那些本地人如何帮助调试器,或者他们是否有所帮助,但我认为他们确实有他们的观点。
具体来说,你的方法实际上不会像jmh_gr所指出的那样编译,因为你不能隐式地将long
强制转换为int
。如果我将j
的类型更改为int
,则在使用调试配置时会生成类似的代码(使用Reflector进行反编译,禁用优化):
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代码。