Каков первый аргумент в конструкторе без параметров?
У меня есть простая программа, например:
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();
}
}
Я решил посмотреть код 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
Интересно, когда я увидел вторую строчку, ldarg.0
, что это значит? this
указатель? Но объект еще не был создан. Как я могу изменить его участников? Мое предположение заключается в том, что перед вызовом конструктора clr
сначала выделяет память для объекта. Затем инициализирует члены значениям по умолчанию, а затем вызывает конструктор. Еще один интересный момент, когда последний вызов объекта. Я думал, что это будет первый.
Ответы
Ответ 1
Инициализаторы полей - это функция С#, а не CLR. Когда вы пишете инициализатор поля, компилятор С# должен помещать код в реализацию этого где-то и где он помещает его внутри тела любых конструкторов.
И так как эти инициализаторы запускают "до" конструктора, то почему последний конструктор базового класса запускается позже.
(И так, да, первый параметр, как вы сделали, this
)
Ответ 2
Хотя объект не "создан" в строгом смысле перед вызовом конструктора, для него должна быть выделена некоторая память. Я не знаю подробностей, но я бы предположил, что все методы экземпляра класса имеют неявный первый параметр, который равен this
; это также будет верно для конструктора, так как ему нужно ссылаться на экземпляр объекта, как и на любой другой метод экземпляра.
Ответ 3
http://www.philosophicalgeek.com/2014/09/29/digging-into-net-object-allocation-fundamentals/
В соответствии с вышеприведенной статьей, CLR выделяет память сначала перед вызовом в конструктор, так же, как создание объекта происходит на С++.