Why is it not possible to get local variable names using Reflection?

徘徊边缘 提交于 2019-12-09 15:14:09

问题


If I have a code like this:

public class Program
{
    public static void Main()
    {
        string bar = "";
        int foo = 24;
    }
}

I can get the local variables declared in Main using:

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

This returns a IList<LocalVariableInfo> and the LocalVariableInfo has only three properties: IsPinned,LocalIndex and LocalType.So there is no Name property exists.

What I'm wondering is that you can see the variable names in the generated 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

but it is not possible to get them using Reflection.Is it because local variables don't have a name and they are only accessed by their indices (if so how the ILDASM.exe shows the names?), or because such feature is not implemented? Or if it is possible using another way then the question would be, how?

Note: I have seen some questions like this and most of them is using Expressions to get variable name. It doesn't work if I would like to get all locals including temporary variables that generated by the compiler.


回答1:


You have to differentiate between the human-readable text-based form of CLI and the machine-readable compiled form of CLI.

In text CLI, local variables indeed can have names (see §II.15.4.1.3 of ECMA-335, as explained in Damien's answer).

But in the binary form, local variables don't have names. For that, look at §II.23.2.6, where the binary format for a method's local variable signature (list of all its local variables) is specified. And it doesn't contain any mention of variable names:

So, if some tool wants to know the original name of a local variable, it has to look into the debugging information contained in the PDB file. If that's not present, there is no way to find out the name.




回答2:


I think you're looking at a Debug build. The id part of the .locals declaration is optional - so there's no guarantee that the names are retained.

See MS Partition II which describes the IL Metadata, section 15.4.1.3 for further details:

MethodBodyItem ::= …
   .locals [ init ] ‘(’ LocalsSignature ‘)’
LocalsSignature ::= Local [ ‘,’ Local ]*
Local ::= Type [ Id ]



回答3:


From MSDN:

Local variable names are not persisted in metadata. In Microsoft intermediate language (MSIL), local variables are accessed by their position in the local variable signature.




回答4:


I think this is because the variable name you see in ILDasm come from the pdb file, not from the assembly itself. If you want to get them, you'll need to read the pdb too.



来源:https://stackoverflow.com/questions/26463480/why-is-it-not-possible-to-get-local-variable-names-using-reflection

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!