Почему необходимо загружать каждый аргумент в стек в методе CIL?

в моем приложении мне нужно динамически создать тип, который содержит несколько свойств. Я знаю, что в подобных случаях необходимо сгенерировать CIL как для методов получения, так и для установки свойства с помощью ILGenerator.

Больше методом проб и ошибок, чем чем-либо еще, я, наконец, пришел к следующему коду, который генерирует для меня метод установки:

MethodBuilder setMethod = customTypeBuilder.DefineMethod(propertyName + "_set", MethodAttributes.Public | MethodAttributes.HideBySig, null, new Type[] {propertyType});
ILGenerator setIlGenerator = setMethod.GetILGenerator();
setIlGenerator.Emit(OpCodes.Ldarg_0);
setIlGenerator.Emit(OpCodes.Ldarg_1);
setIlGenerator.Emit(OpCodes.Stfld, backingField);
setIlGenerator.Emit(OpCodes.Ret);

Код работает достаточно хорошо, но есть одна вещь, которую я в нем не понимаю. Почему необходимо вызывать инструкцию 'Ldarg_0'?

Я знаю, что это относится к неявному первому аргументу метода, ссылке "this", поэтому фактическое значение для установщика хранится во втором аргументе. Я думал, что должно быть достаточно вызвать только инструкцию Ldarg_1, которая затолкнет второй аргумент в стек (в конце концов, в сеттере мне не нужно проверять ссылку «это», поэтому мне не нужно делать с ним что-либо), но это приводит к возникновению TargetInvocationException, когда я пытаюсь установить значение свойства.

Спасибо!


person Nikola Anusev    schedule 12.08.2010    source источник


Ответы (1)


Если бы вы не поместили значение this в стек, как бы Stfld узнать, какое поле объекта нужно изменить? Вы можете попытаться написать сеттер следующим образом:

public int Bizarre
{
    set { otherObject.Field = value; }
}

По сути, Stfld задокументировано для нужно два значения в стеке: одно для «цели» нового значения и одно для самого значения. По общему признанию, диаграмма перехода стека в ECMA 335 более понятна:

…, obj, value => …,

Другими словами: «stfld вытолкнет два верхних элемента из стека».

person Jon Skeet    schedule 12.08.2010
comment
Ах, конечно! Теперь мне почти стыдно, что я задал такой вопрос. Я никогда раньше не писал ни строчки кода на CIL или ассемблере, поэтому иногда довольно сложно разобраться в некоторых концепциях CIL. Но сейчас это кажется очень простым. Большое тебе спасибо! - person Nikola Anusev; 13.08.2010