2017-02-08 10 views
14

У меня есть простая программа, как это:Каков первый аргумент в конструкторе без параметров?

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 сначала выделяет память для объекта. Затем инициализирует члены значениям по умолчанию, а затем вызывает конструктор. Еще один интересный момент, когда последний вызов объекта. Я думал, что это будет первым.

+6

Ваша догадка правильная. arg0 - это 'this'. Обратите внимание, что это относится ко всем методам экземпляра, конструктор не является особым в этом смысле. Точный процесс описан в [newobj opcode docs] (https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.newobj (v = vs.110) .aspx), который используется для выделения и затем инициализации объекта через конструктор. –

+0

@mikez, Отличная ссылка! Это то, что мне нужно – LmTinyToon

ответ

10

Инициализаторы полей - это функция C#, а не CLR. Когда вы пишете инициализатор поля, компилятор C# должен поставить код для реализации этого где-то и где он помещает его внутри тела любых конструкторов.

И поскольку эти инициализаторы запускаются «перед» конструктором, вот почему фактический конструктор базового класса запускается позже.

(А так, да, первый параметр, как вы Inferred, this)

+0

Надеюсь, что с помощью «инициализаторов» вы ссылаетесь на поля, которые были проиндексированы перед любым ctor-вызовом. В отличие от этого * объектно-инициализаторы * запустите * после * конструктора, насколько я знаю. – HimBromBeere

+0

@HimBromBeere - Я надеялся, что из первого параграфа было ясно, что я имею в виду «инициализаторы полей», который является четко определенным термином в C#. Я немного изменил второй пара, чтобы понять, что я все еще ссылаюсь на инициализаторы полей. –

+0

Еще одна интересная мысль о том, почему инициализация была поставлена ​​перед вызовом вызова конструктора базового класса.Возможно, из-за возможного вызова виртуальных методов из конструктора базового класса (который может фактически работать с данными производного класса) – LmTinyToon

3

Хотя объект не «создан» в строгом смысле перед вызовом конструктора, для него должна быть выделена некоторая память. Я не знаю деталей, но я бы предположил, что все методы экземпляра класса имеют неявный первый параметр, который равен this; это также будет верно для конструктора, поскольку ему необходимо ссылаться на экземпляр объекта, как и на любой другой метод экземпляра.

+0

Лучше всего сказать, что объект не * * создан. Все конструкторы базового класса уже запущены, все память, требуемая объектом, уже выделена (включая любые производные классы, для которых конструктор еще не запустился). Это одна из причин, по которой конструкторы должны делать как можно меньше работы - объект полуконструирован, и его утечка каким-либо образом может дать вам огромные головные боли (что происходит, когда вы вызываете виртуальный метод на объект, который не еще есть свой конструктор? Fun: P). – Luaan