正在为双数组生成IL

本文关键字:IL 数组 | 更新日期: 2023-09-27 17:58:33

我正在编写一些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

你知道吗?

正在为双数组生成IL

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会为这两个版本抱怨。

事实上,它运行在第一个版本只是"运气"*。

*原因要复杂得多。