C # में एक संदर्भ प्रकार और मूल्य प्रकार के बीच अंतर क्या है?


100

कुछ लोगों ने मुझसे कुछ महीने पहले यह सवाल पूछा था और मैं इसे विस्तार से नहीं बता सका। एक संदर्भ प्रकार और C # में एक मूल्य प्रकार के बीच क्या अंतर है?

मुझे पता है कि मूल्य प्रकार के होते हैं int, bool, float, आदि और संदर्भ प्रकार के होते हैं delegate, interfaceआदि या यह गलत है, भी है?

क्या आप इसे मुझे पेशेवर तरीके से समझा सकते हैं?


3
एक छोटे नोट के रूप में, मुझे लगता है कि प्रश्न C # के बारे में पूछा गया है, लेकिन वास्तव में यह C # + .NET के बारे में है। आप .NET का विश्लेषण किए बिना C # का विश्लेषण नहीं कर सकते। मैं इस सवाल का जवाब नहीं दूंगा, क्योंकि एक का विश्लेषण करने पर कुछ अंक बनाए जा सकते हैं, दूसरे का विश्लेषण किए बिना (
पुनरावृत्तियों और करीबी

@xanatos यह सीएलआई के बारे में उचित रूप से एक सवाल है, जो C #, VB.Net और, नेट सभी में है। CLI के लिए एक टैग होना चाहिए लेकिन CLI कुछ और के लिए लिया जाता है। सीएलआर है, लेकिन यह एक कार्यान्वयन है, एक मानक नहीं है।
user34660

जवाबों:


172

आपके उदाहरण थोड़े अजीब हैं क्योंकि वे हैं int, boolऔर floatविशिष्ट प्रकार हैं, इंटरफेस और प्रतिनिधि प्रकार के प्रकार हैं - ठीक उसी तरह जैसे structऔर enumमूल्य प्रकार के होते हैं।

मैं लिखा है एक संदर्भ प्रकार और मूल्य प्रकार के स्पष्टीकरण इस लेख में । मुझे किसी भी बिट पर विस्तार करने में खुशी होगी जो आपको भ्रामक लगता है।

"टीएल; डीआर" संस्करण यह सोचने के लिए है कि किसी विशेष प्रकार के एक चर / अभिव्यक्ति का मूल्य क्या है। मान प्रकार के लिए, मान ही जानकारी है। एक संदर्भ प्रकार के लिए, मान एक संदर्भ है जो शून्य हो सकता है या किसी ऑब्जेक्ट को सूचना में रखने का एक तरीका हो सकता है।

उदाहरण के लिए, कागज के एक टुकड़े की तरह एक चर के बारे में सोचो। इस पर लिखा मूल्य "5" या "गलत" हो सकता है, लेकिन इसमें मेरा घर नहीं हो सकता ... इसे मेरे घर के लिए दिशा-निर्देश देना होगा । वे निर्देश एक संदर्भ के बराबर हैं। विशेष रूप से, दो लोगों के पास अलग-अलग कागज के टुकड़े हो सकते हैं, जो मेरे घर के लिए एक ही दिशा-निर्देश हैं - और यदि कोई व्यक्ति उन निर्देशों का पालन करता है और मेरे घर को लाल रंग में रंगता है, तो दूसरा व्यक्ति भी उस बदलाव को देखेगा। यदि वे दोनों सिर्फ कागज पर मेरे घर की अलग-अलग तस्वीरें लेते , तो एक व्यक्ति अपने कागज को रंग देता, दूसरे व्यक्ति के कागज को बिल्कुल भी नहीं बदलता।


2
यह ध्यान रखना महत्वपूर्ण है कि तीन अलग-अलग प्राथमिक प्रकार के शब्दार्थ हैं जो एक चीज की पेशकश कर सकते हैं: अपरिवर्तनीय शब्दार्थ, परस्पर मूल्य शब्दार्थ और परस्पर संदर्भ शब्दार्थ। वैचारिक रूप से, शब्दार्थ के प्रकार एक चीज लागू होता है, चाहे वह स्टैंडअलोन हीप ऑब्जेक्ट या एक चर / क्षेत्र (संरचना) के रूप में संग्रहीत हो। व्यवहार में, जबकि संरचनाएं जो अपने क्षेत्रों को उजागर नहीं करती हैं, वे किसी भी प्रकार के शब्दार्थ को लागू कर सकती हैं, यह तथ्य कि .net ढेर के संदर्भों को साझा करने की अनुमति देता है इसका मतलब है कि ढेर वस्तुओं को परस्पर मूल्य शब्दार्थ को लागू नहीं किया जा सकता है।
सुपरकैट

मैं इस बिट नहीं मिला - while int, bool and float are specific types, interfaces and delegates are kinds of type - just like struct and enum are kinds of value types। क्या आप उदाहरण से मतलब है, बूल विशिष्ट प्रकार के होते हैं? C # उदा, बूल, फ्लोट, क्लास, इंटरफ़ेस, डेलीगेट सब कुछ एक प्रकार है (सटीक होने के लिए डेटा प्रकार)। डेटा प्रकारों को 'संदर्भ प्रकार' और '# में मान प्रकार' के रूप में अलग किया जाता है। फिर आप क्यों कह रहे हैं int एक विशिष्ट प्रकार है लेकिन इंटरफ़ेस एक प्रकार का प्रकार है?
RBT

2
@RBT: डेटा प्रकार नहीं कर रहे हैं बस "संदर्भ प्रकार" और "मान प्रकार" में अलग। उन्हें "क्लास, स्ट्रक्चर, एनम, डेलीगेट, इंटरफ़ेस" में भी अलग किया जाता है। intएक संरचना है, stringएक वर्ग है, Actionएक प्रतिनिधि है, आदि। आपकी सूची "int, बूल, फ्लोट, क्लास, इंटरफ़ेस, प्रतिनिधि" एक सूची है जिसमें विभिन्न प्रकार की चीजें होती हैं, उसी तरह जैसे "10, int" है। विभिन्न प्रकार की चीजों से युक्त एक सूची।
जॉन स्कीट

@JonSkeet संभवतः इस पोस्ट पर उत्तर थोड़ा भ्रामक है।
RBT

@ आरबीटी: मैं कहूंगा कि यह कुछ बुरी तरह से शब्द है, लेकिन भयानक नहीं है।
जॉन स्कीट

26

मान प्रकार:

कुछ मानों को मेमोरी पतों को नहीं रखता है

उदाहरण:

struct

संग्रहण:

टीएल; डीआर : एक चर का मूल्य जहाँ भी घोषित किया जाता है, संग्रहीत किया जाता है। स्थानीय चर उदाहरण के लिए ढेर पर रहते हैं, लेकिन जब एक सदस्य के रूप में एक क्लास के भीतर घोषित यह ढेर कसकर वर्ग उस में घोषित किया जाता है के साथ युग्मित पर रहता है।
लंबे समय तक : चाहे वे कहीं भी घोषित किया गया है इस प्रकार मूल्य प्रकार जमा हो जाती है। उदाहरण के लिए: intएक स्थानीय चर के रूप में एक फ़ंक्शन के अंदर का मान स्टैक पर संग्रहीत किया जाएगा, जबकि intएक वर्ग में सदस्य के रूप में घोषित मूल्य को उस वर्ग के साथ ढेर पर संग्रहीत किया जाएगा, जिसमें एक मूल्य प्रकार है। एक वर्ग के पास एक जीवन रेखा होती है जो कक्षा में घोषित की गई कक्षा के समान ही होती है, जिसमें कचरा संग्रहकर्ता द्वारा लगभग कोई काम नहीं करने की आवश्यकता होती है। हालांकि यह अधिक जटिल है, मैं @ जॉनस्केट की पुस्तक " सी # इन डेप्थ " का उल्लेख करूंगाअधिक संक्षिप्त अन्वेषण के लिए .NET में मेमोरी

लाभ:

एक मान प्रकार को अतिरिक्त कचरा संग्रह की आवश्यकता नहीं है। इसमें रहने वाले इंस्टेंस के साथ कचरा इकट्ठा हो जाता है। विधियों में स्थानीय चर विधि अवकाश पर साफ हो जाते हैं।

कमियां:

  1. जब मानों के बड़े सेट को एक विधि से पारित किया जाता है, तो प्राप्त करने वाला चर वास्तव में कॉपी हो जाता है, इसलिए स्मृति में दो निरर्थक मूल्य होते हैं।

  2. जैसे-जैसे कक्षाएं छूट जाती हैं, वैसे-वैसे सभी ऊप बेनिफिट्स को नुकसान होता है

संदर्भ प्रकार:

मान नहीं मान का स्मृति पता जोड़ता है

उदाहरण:

कक्षा

संग्रहण:

ढेर पर संग्रहीत

लाभ:

  1. जब आप किसी संदर्भ चर को एक विधि में पास करते हैं और यह बदल जाता है तो यह वास्तव में मूल मूल्य को बदल देता है जबकि मूल्य प्रकारों में दिए गए चर की एक प्रति ली जाती है और यह मान बदल जाता है।

  2. जब चर का आकार बड़ा होता है तो संदर्भ प्रकार अच्छा होता है

  3. जैसे ही कक्षाएं एक संदर्भ प्रकार चर के रूप में आती हैं, वे पुन: प्रयोज्य देते हैं, इस प्रकार ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग को लाभ मिलता है

कमियां:

जब आवंटन और dereferences को पढ़ते समय अधिक काम संदर्भित होता है, तो कचरा संग्रहकर्ता के लिए value.extra अधिभार


5
यह जरूरी नहीं है कि संदर्भ प्रकार ढेर पर संग्रहीत होते हैं, और मूल्य प्रकार स्टैक पर संग्रहीत होते हैं। यदि आप अधिक सीखना चाहते हैं तो yoda.arachsys.com/csharp/memory.html पढ़ें ।
Rhys

1
इस जवाब में बहुत सी गलतफहमियां हैं। कृपया जे # रिचर्स सीएलआर को C # के माध्यम से पढ़ें। मान प्रकार थ्रेड स्टैक पर संग्रहीत होते हैं और कचरा संग्रह (जीसी) के अधीन नहीं होते हैं - उनका जीसी के साथ कोई लेना-देना नहीं है। संदर्भ प्रकार प्रबंधित हीप पर संग्रहीत हैं और इसलिए GC के अधीन हैं। यदि Ref प्रकार में एक रूट सन्दर्भ है, तो इसे एकत्र नहीं किया जा सकता है और इसे पीढ़ियों तक, 0, 1 & 2 को बढ़ावा दिया जाता है। यदि इसका कोई रूट सन्दर्भ नहीं है, तो यह गारबेज कलेक्ट किया जा सकता है और फिर इस प्रक्रिया से गुजरता है, जिसे पुनरुत्थान कहा जाता है। मारा जाता है और जीवन में वापस लाया जाता है और फिर अंत में एकत्र किया जाता है।
जेरेमी थॉम्पसन

13

मैंने पाया कि दोनों के अंतर को समझना आसान है यदि आप जानते हैं कि कंप्यूटर मेमोरी में सामान कैसे आवंटित करता है और यह बताता है कि पॉइंटर क्या है।

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

मैं जिस उदाहरण के बारे में बताने जा रहा हूं, वह सरलीकृत है, इसलिए इसे नमक के दाने के साथ लें।

कल्पना कीजिए कि कंप्यूटर मेमोरी एक पंक्ति में पीओ बॉक्स का एक गुच्छा है (w / PO बॉक्स 0001 से पीओ बॉक्स n तक) जो इसके अंदर कुछ रख सकता है। यदि पीओ बॉक्स आपके लिए ऐसा नहीं करता है, तो हैशटेबल या शब्दकोश या एक सरणी या कुछ इसी तरह की कोशिश करें।

इस प्रकार, जब आप कुछ ऐसा करते हैं:

var a = "हैलो";

कंप्यूटर निम्नलिखित कार्य करेगा:

  1. मेमोरी आवंटित करें (5 बाइट्स के लिए मेमोरी लोकेशन 1000 पर शुरू करें) और एच (1000 पर), ई (1001 पर), एल (1002 पर), एल (1003 पर) और ओ (1004 पर) डालें।
  2. स्मृति में कहीं आवंटित करें (स्थान 0500 पर कहें) और इसे चर के रूप में सौंपा।
    तो यह एक उपनाम (0500 एक) की तरह है।
  3. उस मेमोरी लोकेशन (0500) पर 1000 (जो कि स्ट्रींग हैलो मेमोरी में शुरू होता है) पर वैल्यू असाइन करें। इस प्रकार वैरिएबल "हैलो" स्ट्रिंग के वास्तविक शुरुआती मेमोरी लोकेशन का एक संदर्भ है।

मान प्रकार इसकी मेमोरी लोकेशन में वास्तविक चीज़ को रखेगा।

इस प्रकार, जब आप कुछ ऐसा करते हैं:

var a = 1;

कंप्यूटर निम्नलिखित कार्य करेगा:

  1. 0500 पर एक मेमोरी लोकेशन आवंटित करें और इसे वेरिएबल ए (उसी उर्फ ​​चीज़) को असाइन करें
  2. इसमें मान 1 डालें (मेमोरी लोकेशन 0500 पर)।
    ध्यान दें कि हम वास्तविक मान (1) रखने के लिए अतिरिक्त मेमोरी आवंटित नहीं कर रहे हैं। इस प्रकार वास्तव में एक वास्तविक मूल्य है और इसलिए इसे मूल्य प्रकार कहा जाता है।


@, ठीक है, जो मैं कह रहा था, उस तरह के अमान्य को LOL। लेकिन जैसा मैंने कहा, यह दो प्रकारों के बीच कुछ समझ पाने के लिए बड़े पैमाने पर है, जो मेरे मामले में मुझे मददगार लगे। कम से कम मैंने इसे अपने दिमाग में कैसे चित्रित किया :)।
जिमी चंद्रा

8

यह लगभग दो साल पहले एक अलग मंच से मेरा एक पोस्ट है। हालांकि भाषा vb.net है (C # के विपरीत), मान प्रकार बनाम संदर्भ प्रकार की अवधारणाएँ पूरे .net में समान हैं, और उदाहरण भी पकड़ में आते हैं।

यह भी याद रखना महत्वपूर्ण है कि .net के भीतर, सभी प्रकार तकनीकी रूप से आधार प्रकार ऑब्जेक्ट से प्राप्त होते हैं। मान प्रकार को इस तरह के रूप में व्यवहार करने के लिए डिज़ाइन किया गया है, लेकिन अंत में वे आधार प्रकार ऑब्जेक्ट की कार्यक्षमता भी प्राप्त करते हैं।

A. मान प्रकार सिर्फ इतना है कि वे स्मृति में एक अलग क्षेत्र का प्रतिनिधित्व करते हैं जहां एक असतत मूल्य संग्रहीत किया जाता है। मान प्रकार निश्चित मेमोरी आकार के होते हैं और स्टैक में संग्रहीत होते हैं, जो निश्चित आकार के पते का संग्रह होता है।

जब आप इस तरह का बयान करते हैं:

Dim A as Integer
DIm B as Integer

A = 3
B = A 

आपने निम्नलिखित कार्य किए हैं:

  1. 32 बिट पूर्णांक मान रखने के लिए पर्याप्त मेमोरी में 2 स्थान बनाए।
  2. A को सौंपे गए मेमोरी आवंटन में 3 का मान रखा
  3. A में रखे गए मान को असाइन करके B को असाइन किए गए मेमोरी आवंटन में 3 का मान रखा।

प्रत्येक चर का मान प्रत्येक मेमोरी स्थान में विवेकपूर्वक मौजूद होता है।

B. संदर्भ प्रकार विभिन्न आकारों के हो सकते हैं। इसलिए, उन्हें "स्टैक" में संग्रहीत नहीं किया जा सकता है (याद रखें, स्टैक निश्चित आकार के मेमोरी आवंटन का एक संग्रह है)। वे "प्रबंधित हीप" में संग्रहीत हैं। प्रबंधित हीप पर प्रत्येक आइटम को पॉइंटर्स (या "संदर्भ") स्टैक में बनाए रखा जाता है (जैसे पता)। आपका कोड प्रबंधित ढेर में संग्रहीत वस्तुओं तक पहुंचने के लिए स्टैक में इन पॉइंटर्स का उपयोग करता है। इसलिए जब आपका कोड एक संदर्भ चर का उपयोग करता है, तो यह वास्तव में एक पॉइंटर का उपयोग कर रहा है (या प्रबंधित हीप में मेमोरी स्थान के लिए "पता")।

मान लें कि आपने एक स्ट्रिंग प्रॉपर्टी पर्सन के साथ ClsPerson नाम की एक क्लास बनाई है

इस मामले में, जब आप इस तरह का बयान देते हैं:

Dim p1 As clsPerson
p1 = New clsPerson
p1.Name = "Jim Morrison"

Dim p2 As Person

p2 = p1

उपरोक्त मामले में, p1.Name संपत्ति "जिम मॉरिसन" लौटाएगी, जैसा कि आप उम्मीद करेंगे। P2.Name संपत्ति भी "जिम मॉरिसन" को वापस कर देगी, जैसा कि आप चाहते हैं कि मुझे उम्मीद है। मेरा मानना ​​है कि दोनों p1 और P2 स्टैक पर अलग-अलग पते दर्शाते हैं। हालाँकि, अब आपने पी 2 के मूल्य को पी 1 और पी 2 दोनों को नियत किया है, प्रबंधित हीप पर समान स्थान के लिए।

अब COnsider यह स्थिति:

Dim p1 As clsPerson
Dim p2 As clsPerson

p1 = New clsPerson
p1.Name = "Jim Morrison"

p2 = p1

p2.Name = "Janis Joplin"

इस स्थिति में, आपने स्टैक पर एक सूचक p1 के साथ प्रबंधित हीप पर व्यक्ति वर्ग का एक नया उदाहरण बनाया है जो ऑब्जेक्ट को संदर्भित करता है, और ऑब्जेक्ट की नाम संपत्ति को "जिम मॉरिसन" के मान को फिर से असाइन किया है। इसके बाद, आपने Stack में एक और पॉइंटर P2 बनाया, और इसे प्रबंधित हीप पर उसी पते पर इंगित किया जैसा कि p1 द्वारा संदर्भित है (जब आपने असाइनमेंट P2 = p1 बनाया था)।

यहाँ ट्विस्ट आता है। जब आप पी 2 के नाम की संपत्ति असाइन करते हैं तो मूल्य "जैनिस जोप्लिन" आप पी 1 और पी 2 दोनों द्वारा ऑब्जेक्ट के लिए नाम संपत्ति बदल रहे हैं, जैसे कि, यदि आपने निम्न कोड चलाया है:

MsgBox(P1.Name)
'Will return "Janis Joplin"

MsgBox(p2.Name)
'will ALSO return "Janis Joplin"Because both variables (Pointers on the Stack) reference the SAME OBJECT in memory (an Address on the Managed Heap). 

वह समझ में आया था?

पिछले। अगर तुम यह करते हो:

DIm p1 As New clsPerson
Dim p2 As New clsPerson

p1.Name = "Jim Morrison"
p2.Name = "Janis Joplin"

अब आपके पास दो अलग-अलग व्यक्ति ऑब्जेक्ट हैं। हालाँकि, जिस मिनट को आप फिर से करते हैं:

p2 = p1

आपने अब दोनों को "जिम मॉरिसन" की ओर इशारा किया है। (मुझे बिल्कुल यकीन नहीं है कि P2 द्वारा संदर्भित हीप पर ऑब्जेक्ट का क्या हुआ। मैं सोचता हूं कि यह अब दायरे से बाहर है। यह उन क्षेत्रों में से एक है जहां उम्मीद है कि कोई मुझे सीधे सेट कर सकता है।) -आधार: I BELIEVE यही कारण है कि आप नया असाइनमेंट करने से पहले P2 = Nothing या P2 = New clsPerson सेट करेंगे।

एक बार फिर, यदि आप अब ऐसा करते हैं:

p2.Name = "Jimi Hendrix"

MsgBox(p1.Name)
MsgBox(p2.Name)

दोनों msgBox अब "जिमी हेंड्रिक्स" वापस आएंगे

यह थोड़ा भ्रमित करने वाला हो सकता है, और मैं आखिरी बार कहूंगा, मेरे पास कुछ विवरण गलत हो सकते हैं।

गुड लक, और उम्मीद है कि जो लोग मुझसे बेहतर जानते हैं, वे इसमें से कुछ को स्पष्ट करने में मदद करेंगे। । ।


मुझे नहीं पता कि आपको कोई वोट क्यों नहीं मिला। अच्छा जवाब, मुझे स्पष्ट, सरल उदाहरणों से समझने में मदद मिली।
हैरी

के रूप में मूल्य प्रकार बनाम संदर्भ प्रकार अवधारणाओं .net भर वर्दी कर रहे हैं, वे वास्तव में सामान्य भाषा इन्फ्रास्ट्रक्चर में परिभाषित कर रहे हैं (CLI) विनिर्देश, ऐक्मा मानक 335 (यह भी एक आईएसओ मानक)। यह .Net के मानक भाग के लिए मानक है। एक्मा मानक 334 (एक आईएसओ मानक भी) सी # भाषा है और यह स्पष्ट रूप से बताता है कि सी # कार्यान्वयन या तो सीएलआई पर निर्भर होना चाहिए या इस सी # मानक द्वारा आवश्यक न्यूनतम सीएलआई सुविधाओं पर प्राप्त करने के वैकल्पिक तरीके का समर्थन करना चाहिए । VB.Net हालांकि एक मानक नहीं है, यह Microsoft के लिए स्वामित्व है।
user34660

5

मान डेटा प्रकार और संदर्भ डेटा प्रकार

1) मान (डेटा को सीधे शामिल करें) लेकिन संदर्भ (डेटा को संदर्भित करता है)

2) में मूल्य (हर चर अपनी एक प्रतिलिपि है), लेकिन
में संदर्भ (एक से अधिक चर कुछ वस्तुओं का उल्लेख कर सकते हैं)

3) मूल्य में (ऑपरेशन चर अन्य चर पर प्रभाव नहीं कर सकता) लेकिन संदर्भ में (चर अन्य को प्रभावित कर सकता है)

4) मान प्रकार हैं (इंट, बूल, फ्लोट) लेकिन संदर्भ प्रकार हैं (सरणी, वर्ग ऑब्जेक्ट, स्ट्रिंग)


2

मान प्रकार:

  • निश्चित स्मृति का आकार।

  • स्टैक मेमोरी में संग्रहीत।

  • वास्तविक मूल्य प्राप्त करता है।

    पूर्व। int, चार, बूल, आदि ...

संदर्भ प्रकार:

  • निश्चित स्मृति नहीं।

  • ढेर स्मृति में संग्रहीत।

  • वास्तविक मूल्य का मेमोरी पता धारण करता है।

    पूर्व। स्ट्रिंग, सरणी, वर्ग, आदि ...


1

"वेरायबल्स जो मूल्य प्रकारों पर आधारित होते हैं, उनमें सीधे मान शामिल होते हैं। एक मान प्रकार को किसी अन्य चर में समाहित करने के लिए निहित मूल्य को कॉपी करता है। यह संदर्भ प्रकार चर के असाइनमेंट से भिन्न होता है, जो ऑब्जेक्ट के संदर्भ को कॉपी करता है, लेकिन ऑब्जेक्ट को ही नहीं।" Microsoft की लाइब्रेरी से।

आप एक और अधिक पूरा उत्तर मिल सकता है यहाँ और यहाँ


1
मुझे वह स्पष्टीकरण पसंद नहीं है, क्योंकि ऐसा लगता है कि असाइनमेंट संदर्भ प्रकारों और मूल्य प्रकारों के लिए अलग-अलग काम करता है। यह नहीं है दोनों मामलों में, यह "लक्ष्य" चर के मूल्य को अभिव्यक्ति के बराबर बनाता है - मूल्य की प्रतिलिपि बनाई जाती है। अंतर क्या है कि मूल्य है में है -, संदर्भ प्रकार के लिए मूल्य की नकल की हो जाता है कि एक संदर्भ है। हालांकि यह अभी भी चर का मूल्य है।
जॉन स्कीट

मैं आपसे सहमत हूं और मैं पहले से ही जानता हूं कि यह अलग हो सकता है, जैसा कि आप इस लेख में पढ़ सकते हैं । लेकिन, मैं सिर्फ इस विषय के बारे में Microsoft के मार्गदर्शक को दोहरा रहा हूं और यह भी कि आप आमतौर पर पुस्तकों में कैसे पढ़ते हैं। कृपया मुझे दोष मत दो! :)
लुकास एस।

ओह ज़रूर ... वहाँ MSDN प्रलेखन के बिट्स के बहुत सारे हैं जहाँ गलती पाया जा सकता है :)
जॉन स्कीट

1

कभी-कभी स्पष्टीकरण विशेष रूप से शुरुआती लोगों के लिए मदद नहीं करेगा। आप मान प्रकार को डेटा फ़ाइल और संदर्भ प्रकार को फ़ाइल के शॉर्टकट के रूप में देख सकते हैं।

इसलिए यदि आप एक संदर्भ चर की नकल करते हैं, तो आप केवल लिंक / पॉइंटर को मेमोरी में कहीं वास्तविक डेटा पर कॉपी करते हैं। यदि आप एक मूल्य प्रकार की प्रतिलिपि बनाते हैं, तो आप वास्तव में मेमोरी में डेटा को क्लोन करते हैं।


0

यह संभवतः गूढ़ तरीकों से गलत है, लेकिन, इसे सरल बनाने के लिए:

मूल्य प्रकार वे मान होते हैं जो सामान्य रूप से "मूल्य से" पारित होते हैं (इसलिए उन्हें कॉपी करना)। संदर्भ प्रकारों को "संदर्भ द्वारा" पारित किया जाता है (इसलिए मूल मूल्य के लिए एक संकेतक दिया जाता है)। .NET ECMA मानक द्वारा कोई गारंटी नहीं है कि ये "चीज़ें" कहाँ सहेजी गई हैं। आप .NET के क्रियान्वयन का निर्माण कर सकते हैं, जो स्टैकलेस है, या एक है जो कि असहाय है (दूसरा बहुत जटिल होगा, लेकिन आप शायद फाइबर और कई स्टैक का उपयोग कर सकते हैं)

संरचनाएं मूल्य प्रकार (इंट, बूल ... संरचनाएं हैं, या कम से कम के रूप में सिम्युलेटेड हैं ...), कक्षाएं संदर्भ प्रकार हैं।

मान प्रकार System.ValueType से उतरते हैं। संदर्भ प्रकार System.Object से उतरता है।

अब .. अंत में आपके पास मान प्रकार, "संदर्भित ऑब्जेक्ट्स" और संदर्भ हैं (C ++ में उन्हें ऑब्जेक्ट के लिए पॉइंटर्स कहा जाएगा। .NET में वे अपारदर्शी हैं। हम नहीं जानते कि वे क्या हैं। हमारे दृष्टिकोण से वे वस्तु के लिए "हैंडल" हैं। ये पिछले मूल्य प्रकार के समान हैं (वे प्रतिलिपि द्वारा पारित किए जाते हैं)। तो एक वस्तु वस्तु (एक संदर्भ प्रकार) और शून्य या उससे अधिक संदर्भों (जो मूल्य प्रकारों के समान हैं) द्वारा बनाई गई है। जब जीसी संदर्भ होंगे तो जीसी शायद इसे एकत्र करेंगे।

सामान्य तौर पर (.NET के "डिफ़ॉल्ट" कार्यान्वयन में), मान प्रकार स्टैक पर जा सकते हैं (यदि वे स्थानीय क्षेत्र हैं) या हीप पर (यदि वे एक वर्ग के क्षेत्र हैं, अगर वे एक पुनरावृत्ति फ़ंक्शन में चर हैं, तो) यदि वे एक क्लोजर द्वारा संदर्भित चर हैं, यदि वे एक async फ़ंक्शन (नए Async CTP का उपयोग करके) में परिवर्तनशील हैं ...)। संदर्भित मान केवल ढेर पर जा सकता है। संदर्भ मान प्रकार के समान नियमों का उपयोग करते हैं।

मान टाइप के मामलों में जो ढेर पर जाते हैं क्योंकि वे एक इट्रेटर फ़ंक्शन में होते हैं, एक async फ़ंक्शन, या एक क्लोजर द्वारा संदर्भित किया जाता है, यदि आप संकलित फ़ाइल देखते हैं तो आप देखेंगे कि कंपाइलर ने इन चरों को डालने के लिए एक वर्ग बनाया था , और जब आप फ़ंक्शन को कॉल करते हैं तो क्लास बनाया जाता है।

अब, मुझे नहीं पता कि मुझे लंबी बातें कैसे लिखनी हैं, और मेरे जीवन में करने के लिए मेरे पास बेहतर चीजें हैं। यदि आप "सटीक" "अकादमिक" "सही" संस्करण चाहते हैं, तो यह पढ़ें:

http://blogs.msdn.com/b/ericlippert/archive/2010/09/30/the-truth-about-value-types.aspx

15 मिनट हो गए हैं मैं इसे खोज रहा हूँ! यह एमएसडीएन संस्करणों की तुलना में बेहतर है, क्योंकि यह एक संक्षिप्त "लेख का उपयोग करने के लिए तैयार है"।


1
यह गूढ़ तरीकों से अधिक में गलत है। यह मूल रूप से गलत है मैं कहूंगा - क्योंकि संदर्भ प्रकार के मूल्य अभी भी मूल्य द्वारा पारित किए गए हैं; यह सिर्फ इतना है कि मूल्य एक संदर्भ है, एक वस्तु नहीं है। Pobox.com/~skeet/csharp/parameters.html देखें । ओह, और स्थानीय चर ढेर पर भी समाप्त हो सकते हैं, उदाहरण के लिए यदि वे कैप्चर किए गए हैं या पुनरावृत्त ब्लॉक का हिस्सा हैं।
जॉन स्कीट

इटरेटर ब्लॉक कक्षाओं में बदल जाते हैं, इसलिए "आपके पीछे" वे "एक वर्ग के क्षेत्र" हैं। बंद करने के लिए भी। हाँ ... मैं "सूचक" (संदर्भ) और "इंगित" के बीच के अंतर को लिखना भूल गया
xanatos

@xanatos: निश्चित रूप से, वे संकलन के बाद एक वर्ग के क्षेत्र हैं - लेकिन वे अभी भी स्रोत कोड में स्थानीय चर हैं। मैं स्वयं संदर्भों को "मूल्य प्रकार" भी नहीं कहूंगा - मुझे लगता है कि मुझे पता है कि आप कहां से आ रहे हैं, लेकिन मुझे नहीं लगता कि इस तरह से पानी को मैला करना एक अच्छा विचार है।
जॉन स्कीट

@ जों हाँ ... वे एक तीसरे प्रकार के होते हैं, क्योंकि पॉइंटर्स .net में "अपारदर्शी" होते हैं, और वे वैल्यूअवे से नहीं निकलते हैं। लेकिन वे संदर्भों की तुलना में मूल्य प्रकारों के समान हैं। आप उन्हें "रेफ" और "आउट" कर सकते हैं। मुझे पानी को मिट्टी में मिलाना पड़ा क्योंकि "किसी" को पुनरावृत्तियों के काम से हाथ धोना पड़ा।
14

अब मैं जिस लेख की ओर संकेत करता हूं, मैंने पाया है: "तीन प्रकार के मूल्य हैं: (1) मूल्य प्रकार के उदाहरण, (2) संदर्भ प्रकार के उदाहरण, और (3) संदर्भ। (सी # में कोड हेरफेर नहीं कर सकते हैं। उदाहरण के प्रकार सीधे। यह हमेशा एक संदर्भ के माध्यम से ऐसा करता है। असुरक्षित कोड में, सूचक प्रकारों को उनके मूल्यों की भंडारण आवश्यकताओं को निर्धारित करने के प्रयोजनों के लिए मूल्य प्रकारों की तरह व्यवहार किया जाता है। ) "।
xanatos

0

संदर्भ प्रकारों के बारे में सोचने का सबसे सरल तरीका उन्हें "ऑब्जेक्ट-आईडी" के रूप में माना जाता है; एक वस्तु आईडी के साथ एक ही चीजें कर सकते हैं एक बनाने के लिए, एक की नकल, पूछताछ या एक के प्रकार में हेरफेर, या समानता के साथ दो की तुलना करें। ऑब्जेक्ट-आईडी के साथ कुछ और करने का प्रयास उस आईडी द्वारा संदर्भित ऑब्जेक्ट के साथ संकेतित कार्रवाई करने के लिए शॉर्टहैंड माना जाएगा।

मान लीजिए कि मेरे पास कार के दो चर X और Y हैं - एक संदर्भ प्रकार। Y "ऑब्जेक्ट आईडी # 19531" रखने के लिए होता है। अगर मैं "X = Y" कहता हूं, तो इससे X को "ऑब्जेक्ट आईडी # 19531" पर रखने का कारण होगा। ध्यान दें कि न तो X और न ही Y एक कार रखता है। कार, ​​जिसे अन्यथा "ऑब्जेक्ट आईडी # 19531" के रूप में जाना जाता है, को कहीं और संग्रहीत किया जाता है। जब मैंने Y को X में कॉपी किया, तो मैंने जो भी किया वह ID नंबर की कॉपी था। अब मान लीजिए मैं कहता हूं X.Color = Colors.Blue। इस तरह के एक बयान को "ऑब्जेक्ट आईडी # 19531" पर जाने और इसे नीले रंग में पेंट करने के निर्देश के रूप में माना जाएगा। ध्यान दें कि भले ही X और Y अब एक पीली के बजाय एक नीली कार का उल्लेख करते हैं, कथन वास्तव में X या Y को प्रभावित नहीं करता है, क्योंकि दोनों अभी भी "ऑब्जेक्ट आईडी # 19531" को संदर्भित करते हैं, जो अभी भी उसी कार के रूप में है हमेशा से रहा है।


0

परिवर्तनीय प्रकार और संदर्भ मूल्य लागू करना आसान है और अच्छी तरह से डोमेन मॉडल पर लागू किया जाता है, विकास की प्रक्रिया को सुविधाजनक बनाता है।

"मूल्य प्रकार" की मात्रा के आसपास किसी भी मिथक को हटाने के लिए, मैं इस पर टिप्पणी करूंगा कि यह प्लेटफॉर्म पर कैसे संभाला जाता है। NET, विशेष रूप से C # (CSharp) में, जब APIS कहा जाता है और मानों को संदर्भ के द्वारा, हमारे तरीकों और कार्यों में और इन मानों के मार्ग का सही उपचार कैसे करें, भेजें।

इस लेख को चर प्रकार मान और संदर्भ C # में पढ़ें


यह एक अंग्रेजी-केवल क्यू एंड ए साइट है, दुर्भाग्य से = \। हालांकि, जवाब देने की कोशिश करने के लिए धन्यवाद। कृपया पूर्ण उत्तर बनाएं, लिंक के रूप में केवल एड्स के रूप में (लेकिन पूर्ण निरंतर उत्तर के रूप में नहीं)। कृपया जवाब देने का तरीका देखें
जेसी

0

मान vएक मान-प्रकार की अभिव्यक्ति / चर है, और rएक संदर्भ-प्रकार की अभिव्यक्ति / चर है

    x = v  
    update(v)  //x will not change value. x stores the old value of v

    x = r 
    update(r)  //x now refers to the updated r. x only stored a link to r, 
               //and r can change but the link to it doesn't .

तो, एक मूल्य-प्रकार चर वास्तविक मूल्य (5, या "एच") को संग्रहीत करता है। एक संदर्भ-प्रकार वैरिएबल केवल एक रूपक बॉक्स के लिए एक लिंक संग्रहीत करता है जहां मूल्य है।


0

C # में उपलब्ध विभिन्न डेटा प्रकारों की व्याख्या करने से पहले, यह उल्लेख करना महत्वपूर्ण है कि C # एक दृढ़ता से टाइप की जाने वाली भाषा है। इसका मतलब यह है कि प्रत्येक चर, निरंतर, इनपुट पैरामीटर, रिटर्न प्रकार और सामान्य रूप से प्रत्येक मूल्य का मूल्यांकन करने वाले प्रत्येक अभिव्यक्ति का एक प्रकार होता है।

प्रत्येक प्रकार में ऐसी जानकारी होती है जिसे संकलक द्वारा निष्पादन योग्य फ़ाइल में मेटाडेटा के रूप में एम्बेड किया जाएगा जो कि सामान्य भाषा रनटाइम (CLR) द्वारा टाइप की गई सुरक्षा की गारंटी देने के लिए उपयोग की जाएगी जब यह स्मृति को आबंटित करता है और पुनः प्राप्त करता है।

यदि आप जानते हैं कि एक विशिष्ट प्रकार की कितनी मेमोरी आवंटित की गई है, तो आप निम्न प्रकार से आकार ऑपरेटर का उपयोग कर सकते हैं:

static void Main()
{
    var size = sizeof(int);
    Console.WriteLine($"int size:{size}");
    size = sizeof(bool);
    Console.WriteLine($"bool size:{size}");
    size = sizeof(double);
    Console.WriteLine($"double size:{size}");
    size = sizeof(char);
    Console.WriteLine($"char size:{size}");
}

आउटपुट प्रत्येक चर द्वारा आवंटित बाइट्स की संख्या दिखाएगा।

int size:4
bool size:1
double size:8
char size:2

प्रत्येक प्रकार से संबंधित जानकारी हैं:

  • आवश्यक भंडारण स्थान।
  • अधिकतम और न्यूनतम मान। उदाहरण के लिए, Int32 2147483648 और 2147483647 के बीच मूल्यों को स्वीकार करता है।
  • आधार प्रकार यह से विरासत में मिला है।
  • वह स्थान जहाँ चर के लिए मेमोरी को रन समय पर आवंटित किया जाएगा।
  • जिस प्रकार के संचालन की अनुमति है।
  • प्रकार द्वारा सम्‍मिलित सदस्य (विधियाँ, क्षेत्र, घटनाएँ, आदि)। उदाहरण के लिए, यदि हम टाइप इंट की परिभाषा की जांच करते हैं, तो हमें निम्नलिखित संरचना और सदस्य मिलेंगे:

    namespace System
    {
        [ComVisible(true)]
        public struct Int32 : IComparable, IFormattable, IConvertible, IComparable<Int32>, IEquatable<Int32>
        {      
            public const Int32 MaxValue = 2147483647;     
            public const Int32 MinValue = -2147483648;
            public static Int32 Parse(string s, NumberStyles style, IFormatProvider provider);    
            ... 
        }  
    }

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

प्रत्येक प्रक्रिया में, उपलब्ध वर्चुअल मेमोरी को निम्नलिखित 6 अनुभागों में व्यवस्थित किया जाता है, लेकिन इस विषय की प्रासंगिकता के लिए, हम केवल स्टैक और हीप पर ध्यान केंद्रित करेंगे।

स्टैक एक LIFO है (पिछली बार, पहले आउट) डेटा संरचना, ऑपरेटिंग सिस्टम पर एक आकार-निर्भर के साथ (एआरएम के लिए, x86 और x64 मशीनों के लिए विंडोज 1MB आरक्षित है, जबकि लिनक्स 2MB से 8MB तक आरक्षित है संस्करण)।

मेमोरी का यह खंड सीपीयू द्वारा स्वचालित रूप से प्रबंधित किया जाता है। हर बार जब कोई फ़ंक्शन एक नया चर घोषित करता है, तो संकलक स्टैक पर उसके आकार के रूप में एक बड़ा मेमोरी ब्लॉक आवंटित करता है, और जब फ़ंक्शन खत्म हो जाता है, तो चर के लिए मेमोरी ब्लॉक डीलॉक्लेट किया जाता है।

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

कस्टम और बिल्ट-इन प्रकार जबकि C # बिल्ट-इन प्रकारों का एक मानक सेट प्रदान करता है जो पूर्णांक, बूलियन, पाठ वर्णों का प्रतिनिधित्व करता है, और इसी तरह, आप अपने स्वयं के प्रकार बनाने के लिए संरचना, वर्ग, इंटरफ़ेस और एनम जैसे निर्माणों का उपयोग कर सकते हैं।

संरचना निर्माण का उपयोग करते हुए कस्टम प्रकार का एक उदाहरण है:

struct Point
{
    public int X;
    public int Y;
};

मूल्य और संदर्भ प्रकार हम C को निम्न श्रेणियों में वर्गीकृत कर सकते हैं:

  • मान प्रकार
  • संदर्भ प्रकार

मान प्रकार के मान System.ValueType वर्ग से प्राप्त होते हैं और इस प्रकार के चर स्टैक में अपने मेमोरी आवंटन के भीतर उनके मान होते हैं। मूल्य प्रकार की दो श्रेणियां हैं संरचना और एनम।

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

namespace System
{
    [ComVisible(true)]
    public struct Boolean : IComparable, IConvertible, IComparable<Boolean>, IEquatable<Boolean>
    {
        public static readonly string TrueString;
        public static readonly string FalseString;
        public static Boolean Parse(string value);
        ...
    }
}

संदर्भ प्रकार दूसरी ओर, संदर्भ प्रकार में एक चर में संग्रहीत वास्तविक डेटा नहीं होता है, लेकिन ढेर का मेमोरी पता जहां मूल्य संग्रहीत होता है। संदर्भ प्रकारों की श्रेणियां वर्ग, प्रतिनिधि, सरणियाँ और इंटरफ़ेस हैं।

रन समय में, जब एक संदर्भ प्रकार चर घोषित किया जाता है, तो इसमें मूल्य शून्य होता है जब तक कि कोई वस्तु जो नए कीवर्ड का उपयोग करके बनाई गई है, उसे सौंपी जाती है।

निम्न उदाहरण जेनेरिक प्रकार सूची के सदस्यों को दर्शाता है।

namespace System.Collections.Generic
{
    [DebuggerDisplay("Count = {Count}")]
    [DebuggerTypeProxy(typeof(Generic.Mscorlib_CollectionDebugView<>))]
    [DefaultMember("Item")]
    public class List<T> : IList<T>, ICollection<T>, IEnumerable<T>, IEnumerable, IList, ICollection, IReadOnlyList<T>, IReadOnlyCollection<T>
    {
        ...
        public T this[int index] { get; set; }
        public int Count { get; }
        public int Capacity { get; set; }
        public void Add(T item);
        public void AddRange(IEnumerable<T> collection);
        ...
    }
}

यदि आप किसी विशिष्ट ऑब्जेक्ट की मेमोरी एड्रेस का पता लगाना चाहते हैं, तो क्लास System.Runtime.InteropServices अप्रबंधित मेमोरी से प्रबंधित ऑब्जेक्ट तक पहुंचने का एक तरीका प्रदान करता है। निम्नलिखित उदाहरण में, हम एक स्ट्रिंग को हैंडल आवंटित करने के लिए स्थैतिक विधि GCHandle.Alloc () का उपयोग करने वाले हैं और फिर इसका पता पुनः प्राप्त करने के लिए AddrOfPinnedObject विधि।

string s1 = "Hello World";
GCHandle gch = GCHandle.Alloc(s1, GCHandleType.Pinned);
IntPtr pObj = gch.AddrOfPinnedObject();
Console.WriteLine($"Memory address:{pObj.ToString()}");

आउटपुट होगा

Memory address:39723832

संदर्भ आधिकारिक दस्तावेज: https://docs.microsoft.com/en-us/cpp/build/reference/stack-stack-allocations?view=vs-2019


-1

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

देखें ECMA मानक 33, सामान्य भाषा इन्फ्रास्ट्रक्चर (CLI) । सीएलआई भी आईएसओ द्वारा मानकीकृत है। मैं एक संदर्भ प्रदान करूंगा लेकिन ECMA के लिए हमें एक पीडीएफ डाउनलोड करना होगा और यह लिंक संस्करण संख्या पर निर्भर करता है। आईएसओ मानकों में पैसा खर्च होता है।

एक अंतर यह है कि मूल्य प्रकारों को बॉक्सिंग किया जा सकता है लेकिन संदर्भ प्रकार आम तौर पर नहीं हो सकते हैं। अपवाद हैं लेकिन वे काफी तकनीकी हैं।

मान प्रकारों में पैरामीटर-कम आवृत्ति वाले निर्माता या फ़ाइनलाइज़र नहीं हो सकते हैं और वे स्वयं को संदर्भित नहीं कर सकते हैं। खुद को का जिक्र करते हुए उदाहरण के लिए इसका मतलब है कि अगर वहाँ एक मान प्रकार है नोड तो के एक सदस्य नोड एक नहीं हो सकता नोड । मुझे लगता है कि विनिर्देशों में अन्य आवश्यकताएं / सीमाएं हैं, लेकिन यदि ऐसा है तो वे एक साथ एक स्थान पर एकत्रित नहीं होते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.