gpt4 book ai didi

C# IL - 调用构造函数

转载 作者:太空狗 更新时间:2023-10-30 00:07:14 24 4
gpt4 key购买 nike

我正在研究 C# IL 简单示例,但无法理解某些内容。我有一个非常简单的程序:

void Main()
{
C c = new C(1);
}
class C
{
public C(){}
public C(int i){}
}

有CIL:

IL_0001:  ldc.i4.1    
IL_0002: newobj UserQuery+C..ctor
IL_0007: stloc.0 // c

C..ctor:
IL_0000: ldarg.0
IL_0001: call System.Object..ctor
IL_0006: nop
IL_0007: nop
IL_0008: nop
IL_0009: ret

C..ctor:
IL_0000: ldarg.0
IL_0001: call System.Object..ctor
IL_0006: nop
IL_0007: nop
IL_0008: nop
IL_0009: ret

我不明白,虚拟机如何区分应该调用哪个构造函数。有两个相同的标签,唯一的区别似乎是在 main 中推送参数。调用构造函数时是否有更深层次的东西?也许编译器正在提供一些元数据来区分应该调用哪个?

那么让我们假设:

void Main()
{
C c = new C(1);
}
class C
{
public C(){}
public C(int i){ i += 1;}
}

IL_0001: ldc.i4.1
IL_0002: newobj UserQuery+C..ctor
IL_0007: stloc.0 // c

C..ctor:
IL_0000: ldarg.0
IL_0001: call System.Object..ctor
IL_0006: nop
IL_0007: nop
IL_0008: nop
IL_0009: ret

C..ctor:
IL_0000: ldarg.0
IL_0001: call System.Object..ctor
IL_0006: nop
IL_0007: nop
IL_0008: ldarg.1
IL_0009: ldc.i4.1
IL_000A: add
IL_000B: starg.s 01
IL_000D: nop
IL_000E: ret

现在,如何区分调用哪个,在标签级别我们无法区分。

最佳答案

我去做实验了...

我使用了以下代码:

class Program
{
static void Main()
{
CallConstructorA();
CallConstructorB();
}

static void CallConstructorA()
{
GC.KeepAlive(new C());
}

static void CallConstructorB()
{
GC.KeepAlive(new C(1));
}
}

class C
{
public C() { }
public C(int i)
{
GC.KeepAlive(i);
}
}

下面是用Telerik JustDecompile为类Program得到的MSIL:

.class private auto ansi beforefieldinit Test.Program
extends [mscorlib]System.Object
{
.method public hidebysig specialname rtspecialname instance void .ctor () cil managed
{
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
}

.method private hidebysig static void CallConstructorA () cil managed
{
IL_0000: nop
IL_0001: newobj instance void Test.C::.ctor()
IL_0006: call void [mscorlib]System.GC::KeepAlive(object)
IL_000b: nop
IL_000c: ret
}

.method private hidebysig static void CallConstructorB () cil managed
{
IL_0000: nop
IL_0001: ldc.i4.1
IL_0002: newobj instance void Test.C::.ctor(int32)
IL_0007: call void [mscorlib]System.GC::KeepAlive(object)
IL_000c: nop
IL_000d: ret
}

.method private hidebysig static void Main () cil managed
{
.entrypoint
IL_0000: nop
IL_0001: call void Test.Program::CallConstructorA()
IL_0006: nop
IL_0007: call void Test.Program::CallConstructorB()
IL_000c: nop
IL_000d: ret
}
}

所以你可以看到调用是不同的...

第一个说:

        IL_0001: newobj instance void Test.C::.ctor()

第二个说:

        IL_0002: newobj instance void Test.C::.ctor(int32)

所以,我猜是你的反编译器没有显示中间代码的所有细节。事实上,我确实在 LINQPad 中尝试了与上述代码类似的代码,并且两者的调用看起来很相似。


关于如何在二进制中完成注释的细节......老实说我不知道​​。

关于C# IL - 调用构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27585736/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com