C# 无参数构造函数中的第一个参数是什么?

C# 无参数构造函数中的第一个参数是什么?,c#,constructor,cil,C#,Constructor,Cil,我有这样一个简单的程序: public class Foo { public Foo() { } public int MyInt { get; set; } = 10; public List<int> MyList { get; set; } = new List<int>(); } public class Program { static public void Main() { Conso

我有这样一个简单的程序:

public class Foo
{
    public Foo()
    {
    }
    public int MyInt { get; set; } = 10;
    public List<int> MyList { get; set; } = new List<int>();
}

public class Program
{
    static public void Main()
    {
        Console.WriteLine(new Foo().MyInt);
        Console.ReadLine();
    }
}
公共类Foo
{
公共食物(
{
}
公共int MyInt{get;set;}=10;
公共列表MyList{get;set;}=new List();
}
公共课程
{
静态公共void Main()
{
Console.WriteLine(新的Foo().MyInt);
Console.ReadLine();
}
}
我决定看看这样的程序的CIL代码(我对Foo的构造函数感兴趣)。这是:

.method public hidebysig specialname rtspecialname
        instance void  .ctor() cil managed
{
    // Code size       26 (0x1a)
    .maxstack  8
    IL_0000:  ldarg.0
    IL_0001:  ldc.i4.s   10
    IL_0003:  stfld      int32 Foo::'<MyInt>k__BackingField'
    IL_0008:  ldarg.0
    IL_0009:  newobj     instance void class [mscorlib]System.Collections.Generic.List`1<int32>::.ctor()
    IL_000e:  stfld      class [mscorlib]System.Collections.Generic.List`1<int32> Foo::'<MyList>k__BackingField'
    IL_0013:  ldarg.0
    IL_0014:  call       instance void [mscorlib]System.Object::.ctor()
    IL_0019:  ret
} // end of method Foo::.ctor
.method public hidebysing specialname rtspecialname
实例void.ctor()cil托管
{
//代码大小26(0x1a)
.maxstack 8
IL_0000:ldarg.0
IL_0001:ldc.i4.s 10
IL_0003:stfld int32 Foo::“k_BackingField”
IL_0008:ldarg.0
IL_0009:newobj实例无效类[mscorlib]System.Collections.Generic.List`1::.ctor()
IL_000e:stfld类[mscorlib]系统.集合.泛型.列表'1 Foo::'k_BackingField'
IL_0013:ldarg.0
IL_0014:调用实例void[mscorlib]System.Object::.ctor()
IL_0019:ret
}//方法Foo::.ctor的结尾

我想知道,当我看到第二行时,
ldarg.0
,它是什么意思<代码>此指针?但该对象尚未创建。如何修改其成员?我的假设是,在调用构造函数之前,
clr
首先为对象分配内存。然后将成员初始化为默认值,然后调用构造函数。另一个有趣的时刻是对象调用是最后一次。我认为它会是第一个。

尽管在构造函数调用之前,严格意义上说对象并没有“创建”,但必须为它分配一些内存。我不知道细节,但我猜一个类的所有实例方法都有一个隐式的第一个参数,即
this
;构造函数也是如此,因为它需要像任何其他实例方法一样引用对象实例。

字段初始值设定项是C#特性,而不是CLR特性。当您编写字段初始值设定项时,C#编译器必须将实现该项的代码放在某个地方,并且放在任何构造函数的主体中

由于这些初始值设定项是在构造函数“之前”运行的,所以实际的基类构造函数是在之后运行的

(因此,是的,第一个参数是您推断的,
this


根据上述文章,CLR在调用构造函数之前先分配内存,同样的方式在C++中进行对象构造。arg0是此。注意,所有实例方法都是这样,构造函数在这个意义上并不特殊。中描述了具体的过程,该过程用于分配对象,然后通过构造函数初始化对象。@mikez,非常好的链接!这正是我所需要的,我希望通过“初始值设定者”,您指的是在任何ctor调用之前初始化的字段。与此相反,据我所知,对象初始值设定项在构造函数之后运行。@HimBromBeere-我希望从第一段可以清楚地看出,我指的是

字段初始值设定项
,这是C#中定义良好的术语。我稍微修改了第二段,以明确我仍然指的是字段初始值设定项。另一个有趣的想法是为什么在调用基类构造函数之前进行初始化。可能是因为可能从基类构造函数(实际上可以处理派生类的数据)调用虚拟方法@LmTinyToon-我认为您必须在字段初始值设定项、基类构造函数和实例构造函数之间选择一些顺序。由于实例构造函数和基类构造函数都是在同一个“位置”描述的,因此不必考虑这两个构造函数之间的联系更紧密。(对于实例构造函数是
Foo():base(something)
)的场景,更好的方法是在创建对象时没有完成。所有基类构造函数都已运行,对象所需的所有内存都已分配(包括构造函数尚未运行的任何派生类)。这就是构造器应该尽可能少做工作的原因之一——对象是半构造的,以任何方式泄漏它都会给您带来巨大的麻烦(当您对尚未执行其构造器的对象调用虚拟方法时会发生什么?有趣:P)。