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
,LocalIndex
和LocalType
.所以没有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
获取的变量名.如果我想获取所有本地包括编译器生成的临时变量,它就不起作用.
我想你正在看一个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)
您必须区分基于人类可读文本的CLI形式和机器可读的CLI编译形式.
在文本CLI中,局部变量确实可以有名称(参见Damien的答案中解释的ECMA-335的§II.15.4.1.3).
但是在二进制形式中,局部变量没有名称.为此,请查看§II.23.2.6,其中指定了方法的局部变量签名(所有局部变量的列表)的二进制格式.并且它不包含任何变量名称:
因此,如果某个工具想要知道局部变量的原始名称,则必须查看PDB文件中包含的调试信息.如果不存在,则无法找到名称.