2011-06-08 108 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