لماذا من الضروري تحميل كل وسيطة على المكدس في طريقة CIL؟

StackOverflow https://stackoverflow.com/questions/3471608

سؤال

في طلبي ، أحتاج إلى إنشاء نوع ديناميكي يحتوي على خصائص متعددة. أدرك أنه في مثل هذه الحالات ، يتعين على المرء إنشاء CIL لكل من أساليب Getter و Setter الخاصة بالخاصية باستخدام 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"؟

أعلم أنه يشير إلى الوسيطة الأولى الضمنية للطريقة ، المرجع "هذا" ، وبالتالي يتم تخزين القيمة الفعلية للستر في الوسيطة الثانية. اعتقدت أنه يجب أن يكون كافياً استدعاء تعليمات LDARG_1 فقط ، والتي ستدفع الوسيطة الثانية إلى المكدس (في النهاية ، في Setter ، لا أحتاج إلى فحص المرجع "هذا" لذلك لا أحتاج إلى ذلك افعل أي شيء به) ، ولكن هذا ينتج عنه TargetInvocationException عندما أحاول تعيين قيمة الخاصية.

شكرًا لك!

هل كانت مفيدة؟

المحلول

إذا لم تدفع القيمة "هذا" على المكدس ، فكيف يمكن Stfld هل تعرف حقل الكائن الذي يجب تغييره؟ يمكن أن تحاول كتابة وسيلة مثل هذا:

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

أساسًا، Stfld هو موثق للحصول على قيمتين على المكدس: واحدة لـ "الهدف" من القيمة الجديدة ، وواحدة للقيمة نفسها. من المسلم به أن مخطط انتقال المكدس في ECMA 335 أكثر وضوحًا:

…, obj, value => …,

وبعبارة أخرى: "سوف يثني STFLD العناصر الأولى من المكدس".

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top