Конструктор всегда призвал к экземпляру объекта, даже если он без параметров и пуст. Если вы не пишете какой-либо конструктор, по умолчанию он неявно генерируется компилятором.
Это даст вам возможность написать конструктор позже по адресу, без необходимости перекомпилировать код вызова.
Объектная конструкция всегда вызывает конструктор по этой причине, за исключением случаев с краем, таких как 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 является для меня неожиданностью, я не знаю, для чего это.
Почему бы это не назвать? –
@LucasTrzesniewski - Я не предполагаю, что он не должен быть вызван определением, но я подозреваю оптимизацию. – toplel32
Каждый слой в иерархии объекта требует вызова конструктора. Если вы не сделаете это явно, это будет сделано для вас. –