Почему необходимо загружать каждый аргумент в стек в методе CIL? - PullRequest
2 голосов
/ 13 августа 2010

в моем приложении мне нужно динамически создать тип, который содержит несколько свойств.Мне известно, что в таких случаях необходимо сгенерировать 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, которая будет помещать второй аргумент в стек (в конце концов, в установщике мне не нужно проверять ссылку "this", поэтому мне не нужносделать что-нибудь с этим), но это приводит к тому, что TargetInvocationException генерируется, когда я пытаюсь установить значение свойства.

Спасибо!

1 Ответ

4 голосов
/ 13 августа 2010

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

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

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

…, obj, value => …,

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

...