这个CIL有什么问题?

me-*_*e-- 5 .net c# cil mono.cecil

我正在通过Cecil生成一些代码.代码生成没有错误,但当我尝试加载程序集时,我得到:

DataSerializersTest.exe中发生了未处理的"System.InvalidProgramException"类型异常

附加信息:公共语言运行时检测到无效程序.

这是生成的IL:

.method public static 
    class Data.FooData Read (
        class [mscorlib]System.IO.BinaryReader input
    ) cil managed 
{
    // Method begins at RVA 0x3a58
    // Code size 60 (0x3c)
    .maxstack 3
    .locals (
        [0] class Data.FooData,
        [1] valuetype [System.Runtime]System.Nullable`1<int32>
    )

    IL_0000: newobj instance void Data.FooData::.ctor()
    IL_0005: stloc.0
    IL_0006: ldloc.0
    IL_0007: ldarg.0
    IL_0008: callvirt instance bool [System.IO]System.IO.BinaryReader::ReadBoolean()
    IL_000d: ldc.i4.0
    IL_000e: ceq
    IL_0010: brtrue.s IL_001f

    IL_0012: ldarg.0
    IL_0013: callvirt instance int32 [System.IO]System.IO.BinaryReader::ReadInt32()
    IL_0018: newobj instance void valuetype [System.Runtime]System.Nullable`1<int32>::.ctor(!0)
    IL_001d: br.s IL_0028

    IL_001f: nop
    IL_0020: ldloca.s 1
    IL_0022: initobj valuetype [System.Runtime]System.Nullable`1<int32>

    IL_0028: nop
    IL_0029: callvirt instance void Data.FooData::set_I(valuetype [System.Runtime]System.Nullable`1<int32>)
    IL_002e: ldloc.0
    IL_002f: ldarg.0
    IL_0030: callvirt instance string [System.IO]System.IO.BinaryReader::ReadString()
    IL_0035: callvirt instance void Data.FooData::set_Name(string)
    IL_003a: ldloc.0
    IL_003b: ret
} // end of method FooDataReader::Read
Run Code Online (Sandbox Code Playgroud)

等效的C#代码如下所示:

public static FooData Read(BinaryReader input)
{
    var result = new FooData();

    if (input.ReadBoolean())
    {
        result.I = input.ReadInt32();
    }
    else
    {
        result.I = null;
    }

    result.Name = input.ReadString();

    return result;
}
Run Code Online (Sandbox Code Playgroud)

我已经多次通过IL了,这对我来说很有意义.它与C#编译器为上述C#代码生成的内容不同,但我想了解我生成的IL有什么问题.有人能告诉我吗?

Dam*_*ver 7

我想我已经发现了它.initobj没有离开评价堆栈上的新初始化的对象-而newobj做.所以IL_0028到达时堆栈是不平衡的- 如果我们走了newobj路线,那么我们在堆栈上有两个项目(FooDataNullable<int>).如果我们走了initobj路线,那么我们所有的就是FooData堆栈上的对象引用.你需要重新加载本地1:

IL_0022: initobj valuetype [System.Runtime]System.Nullable`1<int32>
         ldloc.1
IL_0028: nop
Run Code Online (Sandbox Code Playgroud)