2015-06-01 3 views
3

Учитывая пустой конструктор, таких как:Есть пустые конструкторы, вызываемые в C#?

internal C() 
{ 
} 

это называется при создании объекта? Он должен содержать только операцию возврата, поэтому теоретически ее можно было бы отбросить, правильно?

Примечание: для меняет, что для каждого класса существует неявный конструктор. Однако намерение этого вопроса; если CLR вызывает конструкторы с исключительно операцией return.

+2

Почему бы это не назвать? –

+0

@LucasTrzesniewski - Я не предполагаю, что он не должен быть вызван определением, но я подозреваю оптимизацию. – toplel32

+0

Каждый слой в иерархии объекта требует вызова конструктора. Если вы не сделаете это явно, это будет сделано для вас. –

ответ

5

Конструктор всегда призвал к экземпляру объекта, даже если он без параметров и пуст. Если вы не пишете какой-либо конструктор, по умолчанию он неявно генерируется компилятором.

Это даст вам возможность написать конструктор позже по адресу, без необходимости перекомпилировать код вызова.

Объектная конструкция всегда вызывает конструктор по этой причине, за исключением случаев с краем, таких как FormatterServices.GetUninitializedObject, который является единственным способом, которым я знаю, чтобы создать объект без вызова конструктора (он используется для целей сериализации).

К слову, newobj IL опкод (который используется для создания экземпляра нового объекта), явно принимает конструктор в качестве входного параметра:

newobj инструкция создает новый объект или новый экземпляр тип значения. Ctor - это токен метаданных (методref или methoddef, который должен быть помечен как конструктор), который указывает имя, класс и подпись вызываемого конструктора.

newobj инструкция выделяет новый экземпляр класса, связанный с т е р и инициализирует все поля в новом экземпляре для 0 (правильного типа) или нулевых ссылок в зависимости от обстоятельств. Затем он вызывает конструктор ctor с данными аргументами вместе с вновь созданным экземпляром. После вызова конструктора исходная ссылка на объект (тип O) помещается в стек.

Так тип создания фактически определен конструктором вызвать, а не сам типа маркеров, что делает конструктор обязательным.


Поскольку вы хотите знать, что делает JIT, вот демонтаж следующей строки в режиме выпуска (SomeClass класс с пустым конструктором по умолчанию):

var inst = new SomeClass(); 

x64:

000007FE95A30093 in   al,dx 
000007FE95A30094 and   byte ptr [rax-73h],cl 
000007FE95A30097 or   eax,0FFEE4014h 
000007FE95A3009C call  000007FEF5062400 
000007FE95A300A1 mov   rbx,rax 
000007FE95A300A4 call  000007FEEC977A00 

x86:

00320050 push  ebp 
00320051 mov   ebp,esp 
00320053 push  esi 
00320054 mov   ecx,28380Ch 
00320059 call  002720D4 
0032005E mov   esi,eax 
00320060 call  72EA2578 
00320065 mov   ecx,eax 
00320067 mov   eax,dword ptr [ecx] 
00320069 mov   eax,dword ptr [eax+2Ch] 
0032006C call  dword ptr [eax+1Ch] 

Хорошо, я не очень свободно владею кодом сборки, но версия x64 выполняет два вызова.Я предполагаю, что первый - это распределение, а второй - вызов конструктора, но я не уверен в этом (VS не позволит мне перейти по этим адресам по какой-то причине). Этот третий (косвенный) call в коде x86 является для меня неожиданностью, я не знаю, для чего это.

+0

'Пустые конструкторы всегда называются'? если у меня есть конструктор с параметрами и явным пустым конструктором, почему он должен быть вызван из contructor с параметрами? https://dotnetfiddle.net/fuMBYR – ASh

+0

@ASh Это не то, что я имел в виду, я неправильно сформулировал свою формулировку, я переформулирую это предложение, чтобы было ясно. –

+0

Эта информация, как правило, надежна, но не учитывает компиляцию JIT. Компилятор JIT может полностью сводить правила виртуальных инструкций. – toplel32

0

Нет, если вы его не дадите, конструктор по умолчанию будет неявно вызываться. Когда объект создается, конструктор передается с nextobjpointer, указывая на текущую ссылку на объект.

1

Нет, конструктор должен не быть отброшена, так как это кажется, что автор класса предназначен он быть обработан только в пределах его объявляющего узла (пометив конструктор как internal).

+0

Это может быть правильно, но согласна ли реализация CLR? – toplel32

+0

Проверьте сами. Вы не сможете * создавать * новые экземпляры типа вне сборки. Но внешние сборки все равно смогут ссылаться на него. – haim770

0

Да, он вызывается для каждого создания объекта, поскольку он является конструктором по умолчанию. Его можно опустить, если у вас нет другого параметризованного конструктора, но если вы используете другие конструкторы, вам нужно указать конструктор по умолчанию. Для получения дополнительной информации см. this

0

Неважно, если вы пишете конструктор или нет. Каждый раз, когда вы объявляете объект любого класса, аннулируется конструктор.

Теперь вы можете использовать этот конструктор явно, чтобы выполнить определенную работу.

Или вы можете просто оставить его пустым или даже не писать в классе.

Сохранение пустой и не записи конструктора полностью аналогично.

Смежные вопросы