使用Reflection.Emit排除对象数组的麻烦

时间:2010-04-04 11:40:31

标签: c# reflection reflection.emit

我正在尝试发布我认为是一个简单的对象数组,这将导致代码类似于下面的示例

object[] parameters = new object[] { a, b, };

当我使用VS在C#中编写上述代码时,我得到以下IL。正如预期的那样。

.locals init (
[0] object[] parameters,
[1] object[] CS$0$0000)

但是,当我尝试直接发送IL时,我只得到一个索引的init数组。有人可以帮我告诉我哪里出错了吗?

这是我正在使用的Emit代码:

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 是不同的。

3 个答案:

答案 0 :(得分:3)

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

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

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

答案 1 :(得分:0)

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

答案 2 :(得分:0)

CS$0$0000变量在这里是因为编译器没有优化变量创建/使用。它将此自动创建的变量用于代码的new object[] { a, b, }部分,然后将创建的对象分配给object[] parameters变量。 这种行为主要是由于IL的基于堆栈的性质。 尝试在发布模式下运行代码,看看它是否得到优化。