सेकेंडिंग फ़्लेल का उत्तर; अधिक संदर्भ के लिए, यहां समस्या का एक संक्षिप्त विश्लेषण है:
जब संकलक IEnumerable
लौटाते हुए एक इटरेटर ब्लॉक को संसाधित करता है, तो यह पुनरावृत्ति तर्क रखने के लिए एक निजी IEnumerable
कक्षा उत्पन्न करता है।
.method private final hidebysig newslot virtual
instance class [mscorlib]System.Collections.Generic.IEnumerator`1<string> 'System.Collections.Generic.IEnumerable<System.String>.GetEnumerator'() cil managed
{
.custom instance void [mscorlib]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = (
01 00 00 00
)
.override method instance class [mscorlib]System.Collections.Generic.IEnumerator`1<!0> class [mscorlib]System.Collections.Generic.IEnumerable`1<string>::GetEnumerator()
// Method begins at RVA 0x57848
// Code size 89 (0x59)
.maxstack 6
.locals init (
[0] bool,
[1] class DOT.Core.MiscHelpers/'<ReadLines>d__0',
[2] class [mscorlib]System.Collections.Generic.IEnumerator`1<string>
)
IL_0000: call class [mscorlib]System.Threading.Thread [mscorlib]System.Threading.Thread::get_CurrentThread()
IL_0005: callvirt instance int32 [mscorlib]System.Threading.Thread::get_ManagedThreadId()
IL_000a: ldarg.0
IL_000b: ldfld int32 DOT.Core.MiscHelpers/'<ReadLines>d__0'::'<>l__initialThreadId'
IL_0010: bne.un IL_0027
सूचना System.Threading.Thread::get_CurrentThread()
और System.Threading.Thread::get_ManagedThreadId();
के लिए कॉल: यह आईएल की शुरुआत 4.0 संकलक द्वारा अपने GetEnumerator
विधि के लिए उत्पन्न है। जनरेटेड विधि ऑप्टिमाइज़ेशन करने के लिए इसका उपयोग करती है, जहां IEnumerable
तुरंत उपभोग किया जाता है [1], वही ऑब्जेक्ट इंस्टेंस लौटाया जाता है (एक कन्स्ट्रक्टर कॉल की लागत को बचाता है)।
निम्नलिखित आईएल 4.5 संकलक द्वारा उत्पन्न होता है:
.method private final hidebysig newslot virtual
instance class [mscorlib]System.Collections.Generic.IEnumerator`1<string> 'System.Collections.Generic.IEnumerable<System.String>.GetEnumerator'() cil managed
{
.custom instance void [mscorlib]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = (
01 00 00 00
)
.override method instance class [mscorlib]System.Collections.Generic.IEnumerator`1<!0> class [mscorlib]System.Collections.Generic.IEnumerable`1<string>::GetEnumerator()
// Method begins at RVA 0x4830c
// Code size 64 (0x40)
.maxstack 2
.locals init (
[0] class DOT.Core.MiscHelpers/'<ReadLines>d__0'
)
IL_0000: call int32 [mscorlib]System.Environment::get_CurrentManagedThreadId()
IL_0005: ldarg.0
IL_0006: ldfld int32 DOT.Core.MiscHelpers/'<ReadLines>d__0'::'<>l__initialThreadId'
IL_000b: bne.un IL_002b
सूचना पिछले विधि से दो कॉल अब System.Environment::get_CurrentManagedThreadId()
ने ले ली है, जो एक संपत्ति है .NET 4.5 में जोड़ा।
चूंकि 4.5 अपग्रेड 4.0 सी # कंपाइलर (csc.exe) को ओवरराइट करता है, इसलिए आपकी मशीन पर 4.0 के लिए संकलित कोड नए आईएल टेम्पलेट का उपयोग करेगा और वेनिला 4.0 इंस्टॉल पर नहीं चलाएगा, जब तक आपके पास .NET 4.0 संदर्भ न हो असेंबली [2], जो कंपाइलर को आईएल के पुराने संस्करण को उत्पन्न करने का कारण बनती है।
[1] पहली बार यह उस धागे पर खपत है जिसने इसे बनाया है (उदाहरण के लिए एक foreach स्टेटमेंट में)।
[2] .NET Framework इंस्टॉलर से .NET 4.0 कंपाइलर निकालना वास्तव में संभव है, और इसके साथ अपने कोड को संकलित करने के लिए अपनी प्रोजेक्ट फ़ाइलों को संशोधित करना संभव है। यह समस्या को हल करने का एक और तरीका हो सकता है, लेकिन यह एक लंबी कहानी है और मैं यहां विवरण में नहीं जाऊंगा
यह "विधि नहीं मिला:' Int32.System "के रूप में भी पॉप अप करता है।Environment.get_CurrentManagedThreadId() '। – EBarr