2010-06-05 10 views
7

मैं this MSDN Magazine article, लेखक राज्यों (जोर मेरा):क्या अनबॉक्सिंग ढेर पर बॉक्स किए गए ऑब्जेक्ट के भीतर मूल्य में पॉइंटर लौटाता है?

ध्यान दें कि हमेशा मुक्केबाजी एक नया वस्तु और प्रतियां अनबॉक्स्ड मूल्य के बिट्स वस्तु को पैदा करता है। दूसरी तरफ, अनबॉक्सिंग बॉक्सर ऑब्जेक्ट के भीतर डेटा को पर पॉइंटर देता है: मेमोरी कॉपी होती है। हालांकि, यह आमतौर पर यह मामला है कि आपका कोड डेटा को द्वारा प्रतिस्थापित किए गए अनबॉक्स किए गए संदर्भ द्वारा इंगित किया गया है।

मैं जो वाक्य बोल्ड किया गया है और उसके बाद की सजा से उलझन में हूं। मैंने जो कुछ भी पढ़ा है, उससे मैंने this MSDN page समेत पढ़ा है, मैंने कभी यह नहीं सुना है कि अनबॉक्सिंग ही ढेर पर मूल्य के लिए एक सूचक देता है। मैं इस धारणा के तहत था कि अनबॉक्सिंग के परिणामस्वरूप आपके पास एक वैरिएबल होगा जिसमें स्टैक पर मूल्य की प्रतिलिपि होगी, जैसा आपने शुरू किया था। आखिरकार, यदि मेरे चर में "ढेर पर मूल्य के लिए सूचक" है, तो मुझे एक मूल्य प्रकार नहीं मिला है, मुझे एक पॉइंटर मिला है।

क्या कोई इसका अर्थ बता सकता है? क्रैक पर लेखक था? (लेख में कम से कम एक अन्य चमकती त्रुटि है)। और यदि यह सत्य है, तो ऐसे मामले क्या हैं जहां "आपका कोड डेटा को अनबॉक्स किए गए संदर्भ द्वारा प्रतिलिपि बनाने के लिए इंगित करेगा"?

मैंने अभी देखा है कि लेख लगभग 10 वर्ष पुराना है, तो हो सकता है कि यह ऐसा कुछ है जो नेट के जीवन में बहुत जल्दी बदल गया।

उत्तर

6

आलेख सटीक है। हालांकि यह वास्तव में पर बात करता है, आईएलएल ऐसा नहीं लगता है कि संकलक उत्पन्न करता है। आखिरकार, एक .NET प्रोग्राम आईएल निष्पादित नहीं करता है, यह आईआईटी से जेआईटी कंपाइलर द्वारा उत्पन्न मशीन कोड निष्पादित करता है।

और अनबॉक्स ओपोड वास्तव में कोड उत्पन्न करता है जो मान प्रकार मान का प्रतिनिधित्व करने वाले ढेर पर बिट्स को पॉइंटर बनाता है। जेआईटी "JIT_Unbox" नामक सीएलआर में एक छोटे से सहायक समारोह में कॉल उत्पन्न करता है। अगर आपको एसएससीएलआई 20 स्रोत कोड मिल गया है तो \ n \ \ \ \ n \ ऑब्जेक्ट :: GetData() फ़ंक्शन पॉइंटर लौटाता है।

वहां से, सबसे अधिक मूल्य पहले सीपीयू रजिस्टर में कॉपी हो जाता है। जो तब कहीं संग्रहीत हो सकता है। यह ढेर होना जरूरी नहीं है, यह एक संदर्भ प्रकार वस्तु (जीसी ढेर) का सदस्य हो सकता है। या एक स्थिर चर (लोडर ढेर)। या इसे स्टैक (विधि कॉल) पर धक्का दिया जा सकता है। या CPU रजिस्टर का उपयोग तब किया जा सकता है जब किसी अभिव्यक्ति में मान का उपयोग किया जाता है।

डीबगिंग करते समय, संपादक विंडो पर राइट-क्लिक करें और मशीन कोड देखने के लिए "Disassembly पर जाएं" चुनें।

+0

मुझे लगता है! धन्यवाद। –

1

बॉक्सिंग एक संदर्भ-प्रकार के उदाहरण (या तो object या एक इंटरफेस) में मूल्य-प्रकार का उदाहरण डालने का कार्य है, और संदर्भ प्रकार ढेर पर आवंटित किए जाते हैं।

'संक्षेप में सी # 4.0' के मुताबिक: "... प्रतिलिपि ऑब्जेक्ट की सामग्री को मूल्य-प्रकार के उदाहरण में वापस लाता है" और यह स्टैक पर तात्पर्य है।

लेख आपको संदर्भ में, लेखक कहता है:

public static void Main() { 

    Int32 v = 5; // Create an unboxed value type variable 
    Object o = v; // o refers to a boxed version of v 
    v = 123;  // Changes the unboxed value to 123 

    Console.WriteLine(v + ", " + (Int32) o); // Displays "123, 5" 
} 

इस कोड से, आप अनुमान लगा सकते हैं कि कितने मुक्केबाजी आपरेशन होते हैं? आप हो सकते हैं यह जानकर आश्चर्य हुआ कि उत्तर तीन है! चलिए कोड को वास्तव में समझने के लिए सावधानीपूर्वक समझें कि क्या चल रहा है। सबसे पहले, एक इंट 32 अनबॉक्स किए गए मान प्रकार (v) को बनाया गया है और 5 में प्रारंभ किया गया है। फिर ऑब्जेक्ट संदर्भ प्रकार (ओ) बनाया गया है और यह v। पर इंगित करना चाहता है लेकिन संदर्भ प्रकारों को हमेशा ढेर में ऑब्जेक्ट्स के लिए इंगित करना चाहिए , इसलिए सी # ने उचित आईएल कोड बॉक्स v पर जेनरेट किया और बॉक्स में संस्करण के पते को संग्रहीत किया। अब 123 अनबॉक्स किया गया है और संदर्भित डेटा को में अनबॉक्स किए गए मान प्रकार v में कॉपी किया गया है; वी के बॉक्स किए गए संस्करण पर इसका प्रभाव नहीं है, इसलिए बॉक्स किए गए संस्करण का मान 5 का मान रखता है। ध्यान दें कि यह उदाहरण दिखाता है कि ओ कैसे अनबॉक्स किया गया है (जो में पॉइंटर को ओ में डेटा देता है), और फिर o में डेटा को अनबॉक्स किए गए मान प्रकार v में कॉपी किया गया है।

+0

हां, मैंने जो कुछ भी पढ़ा है, वह कहता है या तात्पर्य है कि डेटा को स्टैक पर वापस कॉपी किया गया है। इस स्पष्टीकरण के लिए खुद को विरोधाभास के रूप में: हां, और जो उद्धरण आपने बोल्ड में चिपकाया है उसका हिस्सा वास्तव में है जब मैंने कहा कि लेख में कोई त्रुटि हुई थी। यह बिल्कुल गलत है - उदाहरण में कहीं भी v में unboxed नहीं है। –

5

मूल आलेख के लेखक को आईएल स्तर पर क्या हो रहा है इसका जिक्र करना चाहिए। दो अनबॉक्सिंग ओपोडोड मौजूद हैं: unbox और unbox.any

MSDN के अनुसार, regarding unbox.any:

जब एक मान प्रकार की बॉक्स्ड प्रपत्र के लिए आवेदन किया, unbox.any अनुदेश मूल्य obj (ग्रुप ओ के) के भीतर निहित अर्क, और इसलिए है एलबॉक्स के बराबर ldobj के बाद।

और regarding unbox:

[...] Unbox वस्तु से मान प्रकार कॉपी करने के लिए आवश्यक नहीं है। आमतौर पर यह मान प्रकार की गणना करता है जो पहले से बॉक्स किए गए ऑब्जेक्ट के अंदर मौजूद है।

तो लेखक को पता था कि वह किस बारे में बात कर रहा था।

unbox के बारे में यह छोटा तथ्य आईएल के साथ सीधे काम करते समय कुछ निफ्टी अनुकूलन करना संभव बनाता है। उदाहरण के लिए, यदि आपके पास एक बॉक्सिंग int है जिसे आपको एक रेफ इंट को स्वीकार करने वाले फ़ंक्शन को पास करने की आवश्यकता है, तो आप केवल unbox ऑपोड उत्सर्जित कर सकते हैं, और इंट का संदर्भ फ़ंक्शन के संचालन के लिए स्टैक में तैयार होगा। इस मामले में फ़ंक्शन मुक्केबाजी ऑब्जेक्ट की वास्तविक सामग्री को बदल देगा, जो कुछ सी # स्तर पर काफी असंभव है। यह आपको अस्थायी स्थानीय चर के लिए स्थान आवंटित करने की आवश्यकता से बचाता है, वहां int int को अनबॉक्स करता है, फ़ंक्शन के लिए int को रिफ्रेंस पास करता है, और उसके बाद पुराने बॉक्स को छोड़कर int को फिर से बॉक्स करने के लिए एक नया मुक्केबाजी ऑब्जेक्ट बनाता है।

बेशक, जब आप सी # स्तर पर काम कर रहे हों, तो आप ऐसा कोई अनुकूलन नहीं कर सकते हैं, तो आमतौर पर क्या हो रहा है यह है कि कंपाइलर द्वारा उत्पन्न कोड लगभग हमेशा बॉक्स किए गए ऑब्जेक्ट से वेरिएबल को कॉपी करेगा इसका कोई और उपयोग करना।

+0

+1 ग्रेट एडिशन, धन्यवाद। –

संबंधित मुद्दे