我有一个LocalBuilder
,它本质上是一个数组。我可以在IL中使用它,也可以使用OpCodes.Ldlen
加载它的长度。我只是想知道,是否有任何方法可以将长度从堆栈顶部移至某个实际变量。我正在寻找类似的东西
int lengthVariable = 0;
IL.Emit(OpCodes.Ldloc, arr);
IL.Emit(OpCodes.Ldlen);
IL.Emit(??????, lengthVariable);
我想获取此变量,以便可以基于数组的长度运行循环。我知道我可以在IL中创建一个循环,但是我认为如果可能的话,它将更加方便。
编辑:我想在这里做的是
问题是,我现在必须两次调用外部方法。我希望可以从IL数组中获取长度,以便直接循环遍历,而无需两次调用外部方法。我知道我可以在IL中编写一个for循环,但是我有点避免编写IL的分支语句。
您不能像这样填充本地lengthVariable
-它在完全独立的范围/堆栈框架中运行。但是,您可以将方法(DynamicMethod
或MethodBuilder
)更改为return,然后将新方法的委托创建为Func<int>
,然后调用它。
然后您的最后一行将是IL.Emit(Opcodes.Ret);
,以返回本地堆栈上的单个值。或者,您可以使用Opcodes.Stfld
或Opcodes.Stsfld
将值存储到实例或静态字段中。
在评论中讨论之后,似乎这句话
十分棘手-您要获得的最终IL是可以获取的by decompiling existing code,只剩下真正的[[tricky位来处理实际分支目标的标签-但是这仅意味着调用我知道我可以在IL中编写一个for循环,但是我有点避免编写IL的分支语句。
问题上可能是可以克服的;
foreach
不是真的
.DefineLabel()
来声明它们-您可以将它们用作目标,然后知道它们将跳转到的位置-和.MarkLabel()
来放置它们(仅一次)。它不是direct IL(它使用抽象层),但是您可以看到here正在使用此方法-特别是,请注意,它提前使用DefineLabel()
,并在以后标记目标在MarkLabel
。