为什么不能使用Reflection获取局部变量名?

Sel*_*enç 10 c# reflection il local-variables

如果我有这样的代码:

public class Program
{
    public static void Main()
    {
        string bar = "";
        int foo = 24;
    }
}
Run Code Online (Sandbox Code Playgroud)

我可以Main使用以下方法获取声明的局部变量:

var flag = BindingFlags.Static | BindingFlags.Public;
var fields = typeof(Program).GetMethod("Main", flags).GetMethodBody().LocalVariables;
Run Code Online (Sandbox Code Playgroud)

这将返回一个IList<LocalVariableInfo>LocalVariableInfo只有三个属性:IsPinned,LocalIndexLocalType.所以没有Name财产存在.

我想知道的是你可以看到生成的变量名称IL code:

.method public hidebysig static void  Main() cil managed
{
  .entrypoint
  // Code size       11 (0xb)
  .maxstack  1
  .locals init ([0] string bar,
           [1] int32 foo)
  IL_0000:  nop
  IL_0001:  ldstr      ""
  IL_0006:  stloc.0
  IL_0007:  ldc.i4.s   24
  IL_0009:  stloc.1
  IL_000a:  ret
} // end of method Program::Main
Run Code Online (Sandbox Code Playgroud)

但它不可能让它们使用Reflection.是的,因为局部变量没有名称,只能通过它们的索引访问它们(如果是这样,如何ILDASM.exe显示名称?),还是因为没有实现这样的功能?或者,如果有可能使用其他方式,那么问题是,如何

注:我已经看到了类似的一些问题其中大部分是利用Expressions获取的变量名.如果我想获取所有本地包括编译器生成的临时变量,它就不起作用.

Dam*_*ver 6

我想你正在看一个Debug构建.声明的id部分.locals可选的 - 因此无法保证名称被保留.

有关详细信息,请参阅描述IL元数据的MS Partition II,第15.4.1.3节:

MethodBodyItem ::= …
   .locals [ init ] ‘(’ LocalsSignature ‘)’
LocalsSignature ::= Local [ ‘,’ Local ]*
Local ::= Type [ Id ]
Run Code Online (Sandbox Code Playgroud)


svi*_*ick 6

您必须区分基于人类可读文本的CLI形式和机器可读的CLI编译形式.

在文本CLI中,局部变量确实可以有名称(参见Damien的答案中解释的ECMA-335的§II.15.4.1.3).

但是在二进制形式中,局部变量没有名称.为此,请查看§II.23.2.6,其中指定了方法的局部变量签名(所有局部变量的列表)的二进制格式.并且它不包含任何变量名称:

LocalVarSig

因此,如果某个工具想要知道局部变量的原始名称,则必须查看PDB文件中包含的调试信息.如果不存在,则无法找到名称.


Dav*_*idG 5

MSDN

本地变量名称不保留在元数据中。在Microsoft中间语言(MSIL)中,局部变量通过它们在局部变量签名中的位置进行访问。