使用 Reflection.Emit 发出对象数组时出现问题

发布于 2024-08-28 00:31:25 字数 798 浏览 11 评论 0原文

我正在尝试发出我认为是一个简单的对象数组,该数组将生成类似于以下示例的代码

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

猫七 2024-09-04 00:31:25

C# 编译器生成如下代码:

object[] temp = new object[2];
temp[0] = (object)a;
temp[1] = (object)b;
parameters = temp;

temp 变量是您看到的 CS$0$0000。我认为这样做是为了确保初始化数组时可能引发的异常不会在“参数”中留下部分初始化的数组。当代码捕获异常时,这可能会导致意外失败。正如所写,命名变量要么为空,要么完全初始化。好主意。

The C# compiler generates code like this:

object[] temp = new object[2];
temp[0] = (object)a;
temp[1] = (object)b;
parameters = temp;

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.

〃温暖了心ぐ 2024-09-04 00:31:25

如果您仅声明一个本地 (paramValues),那么将仅声明一个本地。如果您需要第二个本地,请再次调用 DeclareLocal。但我不明白你为什么需要这个?宣布你不需要当地人是没有意义的。

If you declare only one local (paramValues) then there will be only one local declared. Call DeclareLocal 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.

预谋 2024-09-04 00:31:25

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 the new object[] { a, b, } part of the code, and then assigns the created object to the object[] 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文