使用 Reflection.Emit 发出对象数组时出现问题
我正在尝试发出我认为是一个简单的对象数组,该数组将生成类似于以下示例的代码
object[] parameters = new object[] { a, b, };
当我使用 VS 在 C# 中编写上述代码时,我得到以下 IL。正如预期的那样,这有效。
.locals init (
[0] object[] parameters,
[1] object[] CS$0$0000)
然而,当我尝试直接发出 IL 时,我只得到一个索引初始化数组。有人可以帮我告诉我哪里出了问题吗?
这是我正在使用的发出代码:
int arraySize = 2;
LocalBuilder paramValues = ilGenerator.DeclareLocal(typeof(object[]));
paramValues.SetLocalSymInfo("parameters");
ilGenerator.Emit(OpCodes.Ldc_I4_S, arraySize);
ilGenerator.Emit(OpCodes.Newarr, typeof(object));
ilGenerator.Emit(OpCodes.Stloc, paramValues);
这是生成的 IL:
.locals init (
[0] object[] objArray)
两个解决方案之间生成的 IL 的其余部分是相同的,但由于某种原因 .locals init 是不同的。
I am trying to Emit what I thought would be a simple object array that would result in code similar to the below example
object[] parameters = new object[] { a, b, };
When I write the above code in C# using VS, I get the following IL. As expected this works.
.locals init (
[0] object[] parameters,
[1] object[] CS$0$0000)
However, when I try and Emit IL directly, I only ever get a one index init array. Can someone help tell me where I've gone wrong here?
Here is the Emit code I'm using:
int arraySize = 2;
LocalBuilder paramValues = ilGenerator.DeclareLocal(typeof(object[]));
paramValues.SetLocalSymInfo("parameters");
ilGenerator.Emit(OpCodes.Ldc_I4_S, arraySize);
ilGenerator.Emit(OpCodes.Newarr, typeof(object));
ilGenerator.Emit(OpCodes.Stloc, paramValues);
Here is the resulting IL:
.locals init (
[0] object[] objArray)
The rest of the resulting IL is identical between the two solutions, but for some reason the .locals init is different.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
C# 编译器生成如下代码:
temp 变量是您看到的 CS$0$0000。我认为这样做是为了确保初始化数组时可能引发的异常不会在“参数”中留下部分初始化的数组。当代码捕获异常时,这可能会导致意外失败。正如所写,命名变量要么为空,要么完全初始化。好主意。
The C# compiler generates code like this:
The temp variable is the CS$0$0000 you see. I think it does this to ensure that an exception that might be raised while initializing the array doesn't leave a partially initialized array in "parameters". Which could cause unexpected failure when code catches the exception. As written, the named variable is either null or fully initialized. Good idea.
如果您仅声明一个本地 (
paramValues
),那么将仅声明一个本地。如果您需要第二个本地,请再次调用DeclareLocal
。但我不明白你为什么需要这个?宣布你不需要当地人是没有意义的。If you declare only one local (
paramValues
) then there will be only one local declared. CallDeclareLocal
another time if you need a second local. But I don't understand why you'd need this? There is no sense in declaring locals that you don't need.CS$0$0000
变量位于此处是因为编译器没有优化变量创建/使用。它使用这个自动创建的变量作为代码的new object[] { a, b, }
部分,然后将创建的对象分配给object[]parameters
变量。这种行为主要是因为 IL 的基于堆栈的性质。
尝试在发布模式下运行代码,看看它是否得到优化。
The
CS$0$0000
variable is here because the compiler didn't optimize variable creation/usages. It uses this automatically created variable for thenew object[] { a, b, }
part of the code, and then assigns the created object to theobject[] parameters
variable.This behaviour is mostly beacuse of the stack-based nature of IL.
Try running the code in Release mode an see if it gets optimized.