ماذا يعني هذا العداد المولد المترجم؟
-
23-08-2019 - |
سؤال
كتبت طريقة معقدة إلى حد ما التي تحققت - عائدات IEnumerable<string>
, ، ولكن عندما تفقد إخراج المحول البرمجي في العاكس، لم أفهم جزءا محددا من التنفيذ الذي تم إنشاؤه بالمترجم IEnumerator
:
void IDisposable.Dispose()
{
switch (this.<>1__state)
{
case 1:
case 2:
case 3:
switch (this.<>1__state) // empty switch! why?!
{
}
break;
default:
return;
try // What?! AFTER return?!
{
}
finally // is the try-finally block anyhow relevant?
{
this.<>m__Finallya();
}
break;
}
this.<>m__Finally7();
}
أنا أظن (أو أمل) أن العاكس في غير محله هدف الإغلاق الخارجي switch
, ، وأنه يجب أن يكون مباشرة بعد return
. وبعد ومع ذلك، لا أفهم لماذا يوجد مفتاح فارغ في حالة 3، أو لماذا m__Finallya
يتم استدعاء في finally
منع. (هل هناك فرق دلالي بين التشغيل بشكل طبيعي وداخل finally
منع؟ بخلاف SER's، التي ليس لديها في التعليمات البرمجية الخاصة بي.)
للإشارة، إليك IL:
.method private hidebysig newslot virtual final
instance void System.IDisposable.Dispose() cil managed
{
.override [mscorlib]System.IDisposable::Dispose
// Code size 69 (0x45)
.maxstack 2
.locals init ([0] int32 CS$0$0000,
[1] int32 CS$0$0001)
IL_0000: ldarg.0
IL_0001: ldfld int32 FBD.TIP.Reader.MissingMessagesReader/'<GetMissingMessages>d__0'::'<>1__state'
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: ldc.i4.1
IL_0009: sub
IL_000a: switch (
IL_001c,
IL_001c,
IL_001c)
IL_001b: ret
IL_001c: ldarg.0
IL_001d: ldfld int32 FBD.TIP.Reader.MissingMessagesReader/'<GetMissingMessages>d__0'::'<>1__state'
IL_0022: stloc.1
IL_0023: ldloc.1
IL_0024: ldc.i4.2
IL_0025: sub
IL_0026: switch (
IL_0035,
IL_0035)
IL_0033: br.s IL_003e
.try
{
IL_0035: leave.s IL_003e
} // end .try
finally
{
IL_0037: ldarg.0
IL_0038: call instance void FBD.TIP.Reader.MissingMessagesReader/'<GetMissingMessages>d__0'::'<>m__Finallya'()
IL_003d: endfinally
} // end handler
IL_003e: ldarg.0
IL_003f: call instance void FBD.TIP.Reader.MissingMessagesReader/'<GetMissingMessages>d__0'::'<>m__Finally7'()
IL_0044: ret
} // end of method '<GetMissingMessages>d__0'::System.IDisposable.Dispose
المحلول
هذا هو ببساطة عاكس يكافح لمواكبة IL الذي تم إنشاؤه (نظرا لأن كتل للماء لا يتعين عليك أن تتصل ب "العادي" C # طالما أنها صالحة IL). على وجه الخصوص، ret
هو بعد finally
منع.
نصائح أخرى
لم تكن قد أظهرت ما يبدو عليه كتلة ITERATOR الأصلية، ولكن تجربتي في التعاكس وإنشائها المترجم هو أنه لا يتمكن دائما من فكه بالكامل بدقة، لأن التحويل البرمجي يستخدم بعض IL الذي لا يحتوي على ما يعادله ج #.
لقد حصلت على مقالة حول تنفيذ كتلة ITERATOR والتي قد تساعدك قليلا، لكنني لا تقلق كثيرا حول ما يبدو عليه الرمز المترجم. في بعض الحالات، يتم تحديد برنامج التحويل البرمجي C # تقريبا رمز غير ضروري على أساس أنه يحتفظ بالمترجم أكثر بساطة. يجب أن تكون كتل للماءات الكهربائية صعبة للغاية للحصول على حق (يمكن أن تصبح معقدة للغاية، مع كتل في النهاية والتخلص من مقطوعة القيادة) لذلك أعتقد أنه من المعقول أن تثق فقط في JIT لتحسين البتات غير الضرورية مثل التبديل / القضية في التعليمات البرمجية التي تم إنشاؤها.
يمكن أن أقول أن مترجم C # غبي، (ربما يكون غبي بعض الشيء). من الممكن أيضا أن يبدو هذا الرمز مختلفا تماما عند تعظيمه بواسطة وقت التشغيل (كل ما يتم حذفه القمامة السيئة).
على أي حال، ربما تكون على دراية آلات الدولة؟ عند كتابة المولدات في C # (Ground Supply) تخبر المحول البرمجي أن ينبعث من نوع مجهول يقوم بتنفيذ هذا المولد كآلة حالة. هذا نهج رسمي لطيف يعني أن تكون قابلة للتحقق. ربما تكون الأسباب التي تجعلها تبدو الطريقة التي تقوم بها.