2012-02-29 7 views
10

मुझे यह जानकर उत्सुकता है कि सी # ऑब्जेक्ट संदर्भों को रनटाइम (.NET CLR में) में स्मृति में कैसे दर्शाया जाता है। कुछ प्रश्न जो दिमाग में आते हैं वे हैं:सी # ऑब्जेक्ट संदर्भ स्मृति/रनटाइम (सीएलआर में) में कैसे प्रदर्शित होते हैं?

  1. ऑब्जेक्ट संदर्भ कितनी मेमोरी पर कब्जा करता है? किसी विधि के दायरे बनाम कक्षा के दायरे में परिभाषित होने पर यह अलग होता है? क्या यह इस क्षेत्र के आधार पर रहता है (ढेर बनाम ढेर)?

  2. किसी ऑब्जेक्ट संदर्भ में बनाए गए वास्तविक डेटा को क्या रखा जाता है? क्या यह केवल एक स्मृति पता है जो उस वस्तु को इंगित करता है जो इसका संदर्भ देता है या इसके लिए और भी कुछ है? क्या यह इस बात पर निर्भर करता है कि क्या इसे कक्षा या विधि के दायरे में परिभाषित किया गया है?

  3. उपरोक्त के समान प्रश्न, लेकिन इस बार संदर्भ के संदर्भ के बारे में बात करते समय, जब किसी ऑब्जेक्ट संदर्भ संदर्भ द्वारा किसी विधि को पारित किया जाता है। 1 और 2 के जवाब कैसे बदलते हैं?

+3

ध्यान दें कि ये प्रश्न सभी कार्यान्वयन विवरण (जो परिवर्तन के अधीन हैं) हैं और वास्तव में सी # के बारे में नहीं बल्कि एनईटी सीएलआर के बारे में हैं। – dlev

+0

चोपपरडेव, अच्छा दिलचस्प सवाल है लेकिन मैं पूछना चाहता हूं कि आप क्या पूछ रहे हैं - एक ऑब्जेक्ट संदर्भ काफी हद तक एक सूचक है और यह आपके कोड पर चल रहे सिस्टम के आर्किटेक्चर के आधार पर केवल 'संख्या' है। यदि आप इस बारे में पूछ रहे हैं कि नेट हेप आवंटन कैसे काम करता है, तो यह पूरी तरह से एक अलग जानवर है। –

+0

बस जोड़ना चाहता था, यहां कोई अपमान नहीं है, मैं यह कहने की कोशिश नहीं कर रहा हूं कि आप नहीं जानते कि आपका क्या मतलब है - बात यह है कि नेट में यह एक संदिग्ध प्रश्न है और यह भविष्य में उपयोगकर्ताओं को ढेर पर मदद करेगा ओवरफ्लो यह जानने के लिए कि हम किस संदर्भ के बारे में बात कर रहे हैं। –

उत्तर

12

यदि आप सी/सी ++ पॉइंटर्स को समझते हैं तो यह उत्तर सबसे आसानी से समझा जाता है। एक सूचक केवल कुछ डेटा का स्मृति पता है।

  1. एक वस्तु संदर्भ एक सूचक है, जो सामान्य रूप से एक 32-बिट CPU पर 4 बाइट, और एक 64-बिट CPU पर 8 बाइट्स के आकार होना चाहिए। यह वही है जहां इसे परिभाषित किया गया है। जहां यह रहता है यह इस बात पर निर्भर करता है कि इसे कहां परिभाषित किया गया है। यदि यह एक वर्ग का क्षेत्र है, तो यह उस वस्तु में ढेर पर रहता है जिसका वह हिस्सा है। यदि यह एक स्थिर क्षेत्र है, तो यह ढेर के एक विशेष खंड में स्थित है जो कचरा संग्रह के अधीन नहीं है। यदि यह एक स्थानीय चर है, तो यह ढेर पर रहता है।

  2. एक ऑब्जेक्ट संदर्भ केवल एक सूचक है, जिसे स्मृति में ऑब्जेक्ट का पता युक्त int या long के रूप में देखा जा सकता है। यह वही है जहां इसे परिभाषित किया गया है।

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

एक बात आपको पता होना चाहिए, मूल्य प्रकार जगह में जमा हो जाती है (वहाँ कोई स्मृति पता है, बजाय वे जमा हो जाती है सीधे जहां स्मृति पता होगा - देखें # 1)। जब उन्हें किसी विधि में पास किया जाता है, तो एक प्रतिलिपि बनाई जाती है और उस प्रतिलिपि विधि में उपयोग की जाती है। जब वे संदर्भ द्वारा पारित होते हैं, तो एक स्मृति पता पारित किया जाता है जो मान प्रकार को स्मृति में रेखांकित करता है, जिससे इसे बदला जा सकता है।

संपादित करें: जैसा कि डीएलवी ने बताया, ये उत्तर कठिन और तेज़ नियम नहीं हैं, क्योंकि ऐसा कोई नियम नहीं है जो कहता है कि यह कैसे होना चाहिए। हालांकि, इन प्रश्नों को लागू करने के लिए .NET निःशुल्क है। हालांकि इसे कार्यान्वित करने का यह सबसे संभावित तरीका है, क्योंकि इंटेल सीपीयू का आंतरिक रूप से काम कैसे होता है, इसलिए किसी भी अन्य विधि का उपयोग करने से अक्षम हो सकता है।

आशा है कि मैंने आपको बहुत भ्रमित नहीं किया है, लेकिन यह पूछने में संकोच न करें कि आपको स्पष्टीकरण की आवश्यकता है या नहीं।

+0

मूल्य प्रकार हमेशा ढेर पर संग्रहीत नहीं होते हैं। –

+2

"मूल्य प्रकार स्टैक पर संग्रहीत हैं": यह सच नहीं है।मूल्य प्रकार ** ** स्टैक पर संग्रहीत किया जा सकता है, लेकिन यह हमेशा मामला नहीं है। जैसे एक संदर्भ प्रकार में एक मान प्रकार फ़ील्ड ढेर पर संग्रहीत होता है, जिस वस्तु से वह संबंधित होता है। वैसे भी +1, क्योंकि आपका उत्तर अधिकतर सही है ... –

+0

@ थॉमस लेवेस्क: स्टैक पर मूल्य प्रकारों के संदर्भ को हटा दिया गया। धन्यवाद! एक व्यापक उत्तर के लिए –

13

.NET Heaps and Stacks यह ढेर और ढेर के काम का एक संपूर्ण उपचार है।

सी # और कई अन्य ढेर का उपयोग सामान्य संदर्भ बात उपयोग में OOP भाषाओं इस संदर्भ में संदर्भ के लिए प्वाइंटर नहीं संभालती है (सी # भी प्वाइंटर उपयोग करने में सक्षम है!) सूचक उपमा कुछ सामान्य अवधारणाओं के लिए इस वैचारिक काम करते हैं, लेकिन मॉडल इस तरह के सवालों के लिए टूट जाता है। इस विषय पर एरिक लिपर्ट की उत्कृष्ट पोस्ट देखें Handles are Not Addresses

यह कहना उचित नहीं है कि हैंडल एक सूचक का आकार है। (हालांकि यह संयोग से समान हो सकता है) हैंडल ऑब्जेक्ट्स के लिए उपनाम हैं, यह आवश्यक नहीं है कि वे किसी ऑब्जेक्ट के लिए औपचारिक पता हों।

इस मामले CLR हैंडल के लिए वास्तविक पते का उपयोग करने के लिए होता है: ऊपर के लिंक से:

... CLR वास्तव में कचरा कलेक्टर के स्वामित्व वाले वस्तुओं के लिए पते के रूप में प्रबंधित वस्तु के संदर्भ को लागू करता है , लेकिन यह कार्यान्वयन विस्तार है।

तो हाँ एक हैंडल शायद एक 32 बिट वास्तुकला पर 4 बाइट, और एक 64 बाइट वास्तुकला पर 8 बाइट्स है, लेकिन यह एक "यकीन है कि के लिए" नहीं है, और यह संकेत की वजह से सीधे नहीं है। कंपाइलर कार्यान्वयन और के आधार पर ध्यान देने योग्य है, पता प्रकारों का उपयोग कुछ प्रकार के पॉइंटर्स आकार में भिन्न हो सकते हैं।

इस संदर्भ के साथ आप शायद इसे सूचक सूचक द्वारा मॉडल कर सकते हैं, लेकिन यह जानना महत्वपूर्ण है कि हैंडल को पते होने की आवश्यकता नहीं है। सीएलआर इसे बदलना चुन सकता है अगर वह भविष्य में चाहता था और सीएलआर के उपभोक्ताओं को बेहतर नहीं पता होना चाहिए।

इस सूक्ष्म बिंदु के एक अंतिम ड्राइव:

यह एक सी # सूचक है:

object myVariable; 

वे ही नहीं हैं:

int* myVariable; 

यह एक सी # हैंडल है।

आप पॉइंटर्स पर गणित जैसी चीजें कर सकते हैं, आपको हैंडल के साथ नहीं करना चाहिए। यदि आपका हैंडल एक सूचक की तरह लागू किया जाता है और आप इसका उपयोग करते हैं जैसे कि यह एक सूचक था, तो आप हैंडल का दुरुपयोग कर रहे हैं जो कुछ तरीकों से आपको परेशानी में डाल सकता है।

+3

यह एक सी # सूचक नहीं है क्योंकि एक प्रबंधित संदर्भ प्रकार के लिए सूचक बनाना अवैध है। 'int *' सी # सूचक प्रकार का एक उदाहरण होगा। –

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