سؤال

كتبت طريقة معقدة إلى حد ما التي تحققت - عائدات 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) تخبر المحول البرمجي أن ينبعث من نوع مجهول يقوم بتنفيذ هذا المولد كآلة حالة. هذا نهج رسمي لطيف يعني أن تكون قابلة للتحقق. ربما تكون الأسباب التي تجعلها تبدو الطريقة التي تقوم بها.

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