为双数组生成IL

时间:2011-06-08 06:55:38

标签: c# il

我正在编写一些IL机构,用于使用System.Reflection.Emit名称空间创建intdouble数组。

为了创建int数组,我正在使用以下代码。

LocalBuilder arr = gen.DeclareLocal(typeof(int));
gen.Emit(OpCodes.Ldc_I4_1);
gen.Emit(OpCodes.Newarr, typeof(int));
gen.Emit(OpCodes.Stloc, arr);
gen.Emit(OpCodes.Ldloc, arr);
gen.Emit(OpCodes.Ldc_I4_0);
gen.Emit(OpCodes.Ldc_I4, 500);
gen.Emit(OpCodes.Stelem_I4);

gen.Emit(OpCodes.Ldloc, arr);
gen.Emit(OpCodes.Ldc_I4_0);
gen.Emit(OpCodes.Ldelem_I4);
gen.Emit(OpCodes.Call,typeof(Console).GetMethod("WriteLine",new Type[]{typeof(int)}));

它按预期工作,并在控制台上打印500个。

同样,我尝试创建double数组,如下所示。

LocalBuilder arr = gen.DeclareLocal(typeof(double));
gen.Emit(OpCodes.Ldc_I4_1);
gen.Emit(OpCodes.Newarr, typeof(double));
gen.Emit(OpCodes.Stloc, arr);
gen.Emit(OpCodes.Ldloc, arr);
gen.Emit(OpCodes.Ldc_I4_0);
gen.Emit(OpCodes.Ldc_R8, 500D);
gen.Emit(OpCodes.Stelem_R8);

gen.Emit(OpCodes.Ldloc, arr);
gen.Emit(OpCodes.Ldc_I4_0);
gen.Emit(OpCodes.Ldelem_I8);
gen.Emit(OpCodes.Call,typeof(Console).GetMethod("WriteLine",new Type[]{typeof(double)}));

不幸的是,这不起作用,当我使用pereview检查生成的程序集时,它给了我以下错误。

Microsoft (R) .NET Framework PE Verifier.  Version  4.0.30319.1
Copyright (c) Microsoft Corporation.  All rights reserved.

[IL]: Error: [C:\temp\Research\Research\bin\Debug\MyMod.exe : Foo::Main][offset 0x00000006][found ref array md
array 'System.Double[]'][expected Double] Unexpected type on the stack.
[IL]: Error: [C:\temp\Research\Research\bin\Debug\MyMod.exe : Foo::Main][offset 0x00000012] Expected single di
mension array.
2 Error(s) Verifying MyMod.exe

此外,我使用ildasm

检查了生成的程序集
.method privatescope static void  Main$PST06000001() cil managed
{
  .entrypoint
  // Code size       28 (0x1c)
  .maxstack  3
  .locals init (float64 V_0)
  IL_0000:  ldc.i4.1
  IL_0001:  newarr     [mscorlib]System.Double
  IL_0006:  stloc.0
  IL_0007:  ldloc.0
  IL_0008:  ldc.i4.0
  IL_0009:  ldc.r8     500.
  IL_0012:  stelem.r8
  IL_0013:  ldloc.0
  IL_0014:  ldc.i4.0
  IL_0015:  ldelem.i8
  IL_0016:  call       void [mscorlib]System.Console::WriteLine(float64)
  IL_001b:  ret
} // end of method Foo::Main

你有什么想法吗?

1 个答案:

答案 0 :(得分:6)

LocalBuilder arr = gen.DeclareLocal(typeof(int));
gen.Emit(OpCodes.Ldc_I4_1);
gen.Emit(OpCodes.Newarr, typeof(int));
gen.Emit(OpCodes.Stloc, arr);

为什么arr不属于int[]类型?

我确信peverify会抱怨这两个版本。

它运行第一个版本的事实只是'运气'*。

*原因要复杂得多。