2011-06-08 66 views
7

我正在写一些IL机构,用于使用System.Reflection.Emit命名空间创建intdouble数组。生成双阵列的IL

创建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 

你有什么想法?

+0

C#生成的il代码段是什么样的? – 2011-06-08 07:05:03

+2

我承认我在IL很低劣,但是不是将数组引用存储到声明类型的局部变量(int/double)中吗?这个地方不应该是某种参考吗? – 2011-06-08 07:19:23

+0

@Damien_The_Unbeliever:是的,我犯了一个错误,并且错误地将数组引用赋值为一个整型变量。 – 2011-06-08 12:30:14

回答

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

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

*原因要复杂得多。

+0

谢谢我做了一个大错误,变量类型应该是double []之后比改我的代码工作 LocalBuilder arr = gen.DeclareLocal(typeof(double []));不幸的是int []数组示例与 一起工作LocalBuilder arr = gen.DeclareLocal(typeof(int)); – 2011-06-08 07:27:53

+3

@Upul:原因很复杂,为什么它工作。系统将'int'视为与指针类型兼容。类似于C允许你做的事情。 – leppie 2011-06-08 07:39:28

+0

我在x86上 - 我认为它会在x64上崩溃吗? (另外,它不是技术上的参考,而不是指针) – 2011-06-08 08:00:49