ValueTypes ऑब्जेक्ट (ReferenceType) से कैसे प्राप्त होते हैं और अभी भी ValueTypes होते हैं?


83

C # कक्षाओं को व्युत्पन्न करने की अनुमति नहीं देता है, लेकिन सभी ValueTypes ऑब्जेक्ट से प्राप्त होते हैं। यह भेद कहाँ बना है?

सीएलआर इसे कैसे संभालता है?


System.ValueTypeCLR प्रकार प्रणाली में काले जादू के प्रकार का परिणाम ।
RBT

जवाबों:


107

C # कक्षाओं को प्राप्त करने की संरचना की अनुमति नहीं देता है

आपका कथन गलत है, इसलिए आपका भ्रम है। सी # करता structs वर्गों से प्राप्त करने के लिए अनुमति देते हैं। सभी संरचनाएं एक ही वर्ग से निकलती हैं, System.ValueType, जो System.Object से निकलती है। और सभी Enums System.Enum से निकलते हैं।

अद्यतन: कुछ (अब हटाए गए) टिप्पणियों में कुछ भ्रम है, जो स्पष्टीकरण को स्पष्ट करता है। मैं कुछ अतिरिक्त प्रश्न पूछूंगा:

क्या आधार प्रकार से संरचनाएं प्राप्त होती हैं?

पूरी तरह से हाँ। हम विनिर्देश के पहले पृष्ठ को पढ़कर इसे देख सकते हैं:

सभी सी # प्रकार, जैसे कि आदिम प्रकार जैसे कि इंट और डबल, एक ही रूट ऑब्जेक्ट प्रकार से विरासत में मिला।

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

क्या अन्य तरीके हैं जो हम जानते हैं कि संरचनात्मक प्रकार आधार प्रकार से प्राप्त होते हैं?

ज़रूर। एक संरचना प्रकार ओवरराइड कर सकता है ToString। ओवरराइडिंग क्या है, यदि इसके आधार प्रकार की आभासी विधि नहीं है? इसलिए इसका आधार प्रकार होना चाहिए। वह आधार प्रकार एक वर्ग है।

क्या मैं अपनी पसंद के वर्ग से उपयोगकर्ता-परिभाषित संरचना प्राप्त कर सकता हूं?

साभार सं। इसका मतलब यह नहीं है कि संरचना एक वर्ग से नहीं निकलती है । संरचनाएं एक वर्ग से निकलती हैं, और इस तरह उस वर्ग के विधर्मी सदस्यों को विरासत में मिलती हैं। वास्तव में, structs कर रहे हैं के लिए आवश्यक एक विशिष्ट वर्ग से प्राप्त करने के: Enums से प्राप्त करने के लिए आवश्यक हैं Enum, structs से प्राप्त करने के लिए आवश्यक हैं ValueType। क्योंकि इन की आवश्यकता होती है , सी # भाषा आपको कोड में व्युत्पत्ति संबंध को बताने से मना करती है

क्यों मना किया?

जब रिश्ते की आवश्यकता होती है , तो भाषा डिजाइनर के पास विकल्प होते हैं: (1) उपयोगकर्ता को आवश्यक झुकाव टाइप करने की आवश्यकता होती है, (2) इसे वैकल्पिक बनाते हैं, या (3) इसे मना करते हैं। प्रत्येक के पास पेशेवरों और विपक्ष हैं, और सी # भाषा डिजाइनरों ने प्रत्येक के विशिष्ट विवरण के आधार पर अलग-अलग रूप से चुना है।

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

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

इसी तरह सभी प्रतिनिधि प्रकार से प्राप्त होते हैं MulticastDelegate, लेकिन C # की आवश्यकता है कि आप ऐसा कहें।

इसलिए, अब हमने यह स्थापित किया है कि C # सभी संरचनाएं एक वर्ग से निकलती हैं

एक वर्ग से विरासत और व्युत्पत्ति के बीच क्या संबंध है ?

कई लोग सी # में विरासत के रिश्ते से भ्रमित हैं। वंशानुक्रम संबंध काफी सीधा है: यदि कोई संरचना, वर्ग या प्रतिनिधि प्रकार D एक वर्ग प्रकार B से निकलता है तो B के विधर्मी सदस्य भी D के सदस्य हैं। यह उतना ही सरल है।

विरासत के संबंध में इसका क्या मतलब है जब हम कहते हैं कि एक मूल्य ValueType से निकलता है? बस यह कि ValueType के सभी धर्मार्थ सदस्य भी संरचना के सदस्य हैं। ToStringउदाहरण के लिए, इस तरह से उनके कार्यान्वयन को कैसे प्राप्त किया जाता है ; यह संरचना के आधार वर्ग से विरासत में मिला है।

सभी विधर्मी सदस्य? पक्का नहीं। क्या निजी सदस्य न्यायसंगत हैं?

हाँ। एक बेस क्लास के सभी निजी सदस्य भी व्युत्पन्न प्रकार के सदस्य हैं। यदि कॉल साइट सदस्य की पहुँच डोमेन में नहीं है, तो बेशक उन सदस्यों को कॉल करना अवैध है । सिर्फ इसलिए कि आपके पास कोई सदस्य नहीं है, इसका मतलब यह नहीं है कि आप इसका उपयोग कर सकते हैं!

अब हम मूल उत्तर के साथ जारी रखते हैं:


सीएलआर इसे कैसे संभालता है?

बहुत बढ़िया। :-)

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

इसे इस तरह देखो। मान लीजिए कि मैंने आपको निम्नलिखित तथ्य बताए:

  • दो तरह के बॉक्स होते हैं, लाल बॉक्स और ब्लू बॉक्स।

  • हर लाल डिब्बा खाली है।

  • ओ, वी और ई नामक तीन विशेष नीले बक्से हैं।

  • O किसी भी बॉक्स के अंदर नहीं है।

  • V, O के अंदर है।

  • E, V के अंदर है।

  • कोई दूसरा ब्लू बॉक्स V के अंदर नहीं है।

  • कोई ब्लू बॉक्स ई के अंदर नहीं है।

  • हर लाल बॉक्स V या E में है।

  • O के अलावा प्रत्येक ब्लू बॉक्स एक नीले बॉक्स के अंदर है।

नीले बॉक्स संदर्भ प्रकार हैं, लाल बॉक्स मूल्य प्रकार हैं, O सिस्टम है। विशेषण, V सिस्टम है। ValueType, E System.Enum है, और "अंदर" संबंध "से व्युत्पन्न" है।

यह नियमों का पूरी तरह से सुसंगत और सीधा सेट है जिसे आप आसानी से लागू कर सकते हैं, यदि आपके पास बहुत से कार्डबोर्ड और बहुत धैर्य है। चाहे बॉक्स लाल हो या नीला इसका अंदर क्या है, इससे कोई लेना-देना नहीं है; वास्तविक दुनिया में नीले बॉक्स के अंदर लाल बॉक्स लगाना पूरी तरह से संभव है। सीएलआर में, यह एक वैल्यू टाइप बनाने के लिए पूरी तरह से कानूनी है जो एक संदर्भ प्रकार से विरासत में मिलता है, इसलिए जब तक कि यह System.ValueType या System.Enum है।

तो चलिए आपका सवाल फिर से बताते हैं:

ValueTypes ऑब्जेक्ट (ReferenceType) से कैसे प्राप्त होते हैं और अभी भी ValueTypes होते हैं?

जैसा

यह कैसे संभव है कि हर लाल बॉक्स (मूल्य प्रकार) अंदर है (बॉक्स से निकलता है) O (System.Object), जो एक नीला बॉक्स (एक संदर्भ प्रकार) है और अभी भी एक लाल बॉक्स (एक मूल्य प्रकार) है?

जब आप इसे इस तरह वाक्यांश देते हैं, तो मुझे आशा है कि यह स्पष्ट है। बॉक्स V के अंदर लाल बॉक्स लगाने से कुछ भी नहीं है, जो बॉक्स O के अंदर है, जो नीला है। क्यों होगा?


अतिरिक्त अद्यतन:

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


8
भाषा निर्माण सार्थक होना चाहिए। एक मनमाना संदर्भ प्रकार से व्युत्पन्न एक मनमाना मूल्य प्रकार का क्या अर्थ होगा ? क्या ऐसी कोई योजना है जिसे आप उपयोगकर्ता द्वारा परिभाषित निहित रूपांतरणों के साथ भी पूरा नहीं कर सकते?
एरिक लिपर्ट

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

8
ओह समझा। आप इनहेरिटेंस का उपयोग करना चाहते हैं, न कि मॉडलिंग के लिए एक तंत्र के रूप में "एक तरह का" रिश्ते हैं, बल्कि केवल संबंधित प्रकारों के एक समूह के बीच कोड साझा करने के लिए एक तंत्र के रूप में। यह एक उचित परिदृश्य की तरह लगता है, हालांकि व्यक्तिगत रूप से मैं कोड-साझाकरण सुविधा के रूप में विरासत के उपयोग से बचने की कोशिश करता हूं।
एरिक लिपर्ट

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

2
@ सिपो: अब, निष्पक्ष होने के लिए, सवाल में "सीएलआर इसे कैसे संभालता है?" और जवाब यह बताने का एक अच्छा काम करता है कि सीएलआर इन नियमों को कैसे लागू करता है। लेकिन यहाँ बात यह है: हमें यह उम्मीद करनी चाहिए कि जिस प्रणाली से किसी भाषा का कार्यान्वयन होता है, भाषा के समान नियम नहीं होते हैं! कार्यान्वयन प्रणालियाँ आवश्यक रूप से निम्न-स्तरीय होती हैं, लेकिन चलो उस निम्न-स्तरीय प्रणाली के नियमों को भ्रमित नहीं करते हैं जो उस पर निर्मित उच्च-स्तरीय प्रणाली के नियमों के साथ होती हैं। निश्चित रूप से, सीएलआर प्रकार प्रणाली बॉक्सिंग और अनबॉक्स किए गए मूल्य प्रकारों के बीच अंतर करती है, जैसा कि मैंने अपने उत्तर में उल्लेख किया है। लेकिन C # नहीं करता है
एरिक लिपर्ट

21

लघु सुधार, C # केवल कुछ वर्गों से नहीं, किसी भी चीज़ से कस्टम व्युत्पन्न करने की अनुमति नहीं देता है। सभी एक संरचना ऐसा कर सकती है जो एक अंतरफलक को लागू करे जो व्युत्पत्ति से बहुत अलग हो।

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


+1 किसी भी चीज से प्राप्त नहीं होने वाली संरचना के बारे में अच्छे बिंदु के लिए [सिस्टम से स्पष्ट रूप से व्युत्पन्न को छोड़कर। वेल्यू टाइप)।
रीड कोपसे

2
आप कहते हैं कि ValueTypeयह विशेष है, लेकिन यह स्पष्ट रूप से ध्यान देने योग्य है कि ValueTypeवास्तव में एक संदर्भ प्रकार है।
ल्यूक

यदि आंतरिक रूप से किसी वर्ग से प्राप्त होने वाली संरचनाओं के लिए यह संभव है, तो वे इसे सभी के लिए उजागर क्यों नहीं करते हैं?
Joan Venge

1
@ जोआन: वे वास्तव में नहीं हैं। यह सिर्फ इतना है कि आप किसी वस्तु को एक संरचना दे सकते हैं, और उपयोगिता के लिए। लेकिन तकनीकी रूप से, जब वर्गों को कैसे लागू किया जाता है, इसकी तुलना में, मान प्रकार सीएलआर द्वारा पूरी तरह से अलग किए जाते हैं।
रीड कोपसे

2
@JoanVenge मुझे विश्वास है कि भ्रम यहाँ कह रहा है कि CLR के भीतर ValueType वर्ग से संरचनाएँ निकलती हैं। मेरा मानना ​​है कि यह कहना अधिक सही है कि सीएलआर के भीतर, संरचनाएं वास्तव में मौजूद नहीं हैं, सीएलआर के भीतर "संरचना" का कार्यान्वयन वास्तव में वैल्यू टाइप क्लास है। इसलिए ऐसा नहीं है कि सीएलआर में वैल्यू टाइप से एक संरचना विरासत में मिली है।
वायर्ड_इन

20

यह CLR द्वारा बनाए गए कुछ हद तक कृत्रिम निर्माण है, ताकि सभी प्रकार के System.Object के रूप में व्यवहार किया जा सके।

मूल्य प्रकार के माध्यम से System.Object से निकाले जाते हैं System.ValueType है, जो है, जहां विशेष हैंडलिंग होता है (यानी: CLR हैंडल मुक्केबाजी / unboxing, किसी भी प्रकार ValueType से पाने के लिए आदि)।


6

आपका कथन गलत है, इसलिए आपका भ्रम है। C # कक्षाओं से व्युत्पन्न करने की अनुमति देता है। सभी संरचनाएं एक ही वर्ग से निकलती हैं, System.ValueType

तो चलिए इसे आजमाते हैं:

 struct MyStruct :  System.ValueType
 {
 }

यह भी संकलन नहीं होगा। कंपाइलर आपको याद दिलाएगा कि "टाइप लिस्ट 'System.ValueType' इंटरफ़ेस सूची में इंटरफ़ेस नहीं है"।

जब एक संरचना है जो डिकम्पाइल Int32, आप पाएंगे:

सार्वजनिक संरचना Int32: IComparable, IFormattable, IConvertible {}, यह उल्लेख नहीं करने के लिए कि यह System.ValueType से लिया गया है। लेकिन ऑब्जेक्ट ब्राउज़र में, आपको लगता है कि Int32 System.ValueType से इनहेरिट करता है।

तो ये सभी मुझे विश्वास करने के लिए प्रेरित करते हैं:

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


.NET में समान डेटा स्ट्रक्चर्स का उपयोग मूल्य प्रकारों और संदर्भ प्रकारों की सामग्री का वर्णन करने के लिए किया जाता है, लेकिन जब CLR एक प्रकार की परिभाषा देखता है जिसे व्युत्पन्न के रूप में परिभाषित किया जाता है ValueType, तो यह दो प्रकार की वस्तुओं को परिभाषित करने के लिए उपयोग करता है: एक ढेर वस्तु प्रकार एक संदर्भ प्रकार की तरह व्यवहार करता है, और एक भंडारण स्थान प्रकार जो प्रभावी रूप से टाइप-इनहेरिटेंस सिस्टम के बाहर होता है। क्योंकि उन दो प्रकार की चीजों का उपयोग परस्पर-अनन्य संदर्भों में किया जाता है, इसलिए दोनों के लिए एक ही प्रकार के विवरणकों का उपयोग किया जा सकता है। सीएलआर स्तर पर, एक संरचना को उस वर्ग के रूप में परिभाषित किया जाता है जिसके माता-पिता हैं System.ValueType, लेकिन C # ...
2

... यह निर्दिष्ट करने से मना करना कि संरचनाएं किसी भी चीज़ से विरासत में मिली हैं क्योंकि केवल एक चीज़ है जिसे वे ( System.ValueType) से विरासत में प्राप्त कर सकते हैं , और वर्गों को यह निर्दिष्ट करने से मना करते हैं कि वे विरासत में मिले हैं System.ValueTypeक्योंकि किसी भी वर्ग को जिस तरह से घोषित किया गया था, वह मूल्य प्रकार की तरह व्यवहार करेगा।
सुपरकैट

3

एक बॉक्सिंग मूल्य प्रकार प्रभावी रूप से एक संदर्भ प्रकार है (यह एक की तरह चलता है और एक की तरह चलता है, इसलिए प्रभावी रूप से यह एक है)। मेरा सुझाव है कि ValueType वास्तव में आधार प्रकारों का प्रकार नहीं है, बल्कि आधार संदर्भ प्रकार है, जिस पर ऑब्जेक्ट प्रकार टाइप करने पर मूल्य प्रकार परिवर्तित किए जा सकते हैं। गैर-बॉक्सिंग मूल्य प्रकार स्वयं वस्तु पदानुक्रम के बाहर हैं।


1
मुझे लगता है कि आपका मतलब है, "ValueType वास्तव में आधार प्रकार के मूल्य प्रकार नहीं है"
wired_in

1
@ वायर्ड_इन: धन्यवाद। सही किया।
सुपरकैट

2

दलील

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

 

प्रस्ताव

यह उत्तर मेरी अपनी रिवर्स इंजीनियरिंग और सीएलआई विनिर्देश पर आधारित है।

structऔर classC # कीवर्ड हैं। जहां तक ​​सीएलआई का संबंध है, सभी प्रकार (वर्ग, इंटरफेस, संरचना, आदि) को कक्षा की परिभाषाओं द्वारा परिभाषित किया गया है।

उदाहरण के लिए, एक ऑब्जेक्ट प्रकार (C # के रूप में जाना जाता है class) को निम्नानुसार परिभाषित किया गया है:

.class MyClass
{
}

 

एक इंटरफ़ेस interfaceशब्दार्थ विशेषता के साथ एक वर्ग परिभाषा द्वारा परिभाषित किया गया है :

.class interface MyInterface
{
}

 

मूल्य प्रकारों के बारे में क्या?

कारण है कि संरचना से विरासत में मिल सकता है System.ValueTypeऔर अभी भी मूल्य प्रकार हो सकता है, क्योंकि .. वे नहीं है।

मूल्य प्रकार सरल डेटा संरचनाएं हैं। मान प्रकार कुछ से विरासत में नहीं मिलते हैं और वे इंटरफेस को लागू नहीं कर सकते हैं । मूल्य प्रकार किसी भी प्रकार के उपप्रकार नहीं हैं, और उनके पास किसी भी प्रकार की जानकारी नहीं है। एक मान प्रकार के स्मृति पते को देखते हुए, यह पहचानना संभव नहीं है कि किसी संदर्भ प्रकार के विपरीत मान जो किसी छिपे हुए क्षेत्र में टाइप जानकारी रखता है, का प्रतिनिधित्व करता है।

यदि हम निम्नलिखित C # संरचना की कल्पना करते हैं:

namespace MyNamespace
{
    struct MyValueType : ICloneable
    {
        public int A;
        public int B;
        public int C;

        public object Clone()
        {
            // body omitted
        }
    }
}

निम्नलिखित उस संरचना की IL वर्ग परिभाषा है:

.class MyNamespace.MyValueType extends [mscorlib]System.ValueType implements [mscorlib]System.ICloneable
{
    .field public int32 A;
    .field public int32 B;
    .field public int32 C;

    .method public final hidebysig newslot virtual instance object Clone() cil managed
    {
        // body omitted
    }
}

तो यहां क्या हो रहा है? यह स्पष्ट रूप से फैली हुई है System.ValueType, जो एक वस्तु / संदर्भ प्रकार है, और लागू होती है System.ICloneable

स्पष्टीकरण यह है कि जब एक वर्ग परिभाषा का विस्तार होता है तो System.ValueTypeयह वास्तव में 2 चीजों को परिभाषित करता है: एक मूल्य प्रकार, और मूल्य प्रकार का संबंधित बॉक्सिंग प्रकार। वर्ग परिभाषा के सदस्य मूल्य प्रकार और संबंधित बॉक्सिंग प्रकार दोनों के लिए प्रतिनिधित्व को परिभाषित करते हैं। यह वह मूल्य प्रकार नहीं है जो विस्तार और लागू होता है, यह उसी प्रकार का बॉक्सिंग प्रकार है जो करता है। extendsऔर implementsकीवर्ड को केवल बॉक्स्ड प्रकार के लिए लागू।

स्पष्ट करने के लिए, ऊपर दी गई कक्षा परिभाषा 2 चीजें करती है:

  1. 3 फ़ील्ड (और एक विधि) के साथ एक मूल्य प्रकार को परिभाषित करता है। यह किसी भी चीज़ से विरासत में नहीं मिलता है, और यह किसी भी इंटरफेस को लागू नहीं करता है (मूल्य प्रकार न तो कर सकते हैं)।
  2. 3 फ़ील्ड के साथ एक ऑब्जेक्ट प्रकार (बॉक्सिंग प्रकार) को परिभाषित करता है (और एक इंटरफ़ेस विधि लागू करना), इंटरफ़ेस से इनहेरिट करना System.ValueTypeऔर कार्यान्वित करना System.ICloneable

यह भी ध्यान दें, कि किसी भी वर्ग की परिभाषा का विस्तार System.ValueTypeभी आंतरिक रूप से सील है, चाहे वह sealedकीवर्ड निर्दिष्ट किया गया हो या नहीं।

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

 

अब, यदि आप C # जैसे किसी विधि को परिभाषित करने वाले थे

public static void BlaBla(MyNamespace.MyValueType x),

तुम्हें पता है कि विधि मूल्य प्रकार ले जाएगा MyNamespace.MyValueType

ऊपर, हमने पाया कि structC # में कीवर्ड से मिलने वाली वर्ग परिभाषा वास्तव में एक मूल्य प्रकार और एक वस्तु प्रकार दोनों को परिभाषित करती है। हम केवल परिभाषित मूल्य प्रकार का उल्लेख कर सकते हैं, हालांकि। भले ही सीएलआई विनिर्देश बताता है कि बाधा कीवर्ड boxedका उपयोग किसी प्रकार के बॉक्सिंग संस्करण को संदर्भित करने के लिए किया जा सकता है, यह कीवर्ड मौजूद नहीं है (ECMA-335, II.13.1 संदर्भ मूल्य प्रकार देखें)। लेकिन कल्पना करता है कि यह एक पल के लिए करता है।

आईएल में प्रकारों का संदर्भ देते समय, कुछ बाधाओं का समर्थन किया जाता है, जिनमें से हैं classऔर valuetype। यदि हम उपयोग valuetype MyNamespace.MyTypeकरते हैं तो हम MyNamespace.MyType नामक मान प्रकार वर्ग परिभाषा निर्दिष्ट कर रहे हैं। इसी तरह, हम class MyNamespace.MyTypeMyNamespace.MyType नामक ऑब्जेक्ट प्रकार वर्ग परिभाषा को निर्दिष्ट करने के लिए उपयोग कर सकते हैं । जिसका अर्थ है कि IL में आपके पास एक ही नाम के साथ एक मान प्रकार (संरचना) और एक ऑब्जेक्ट प्रकार (वर्ग) हो सकता है और फिर भी उन्हें अलग कर सकता है। अब, यदि boxedCLI विनिर्देश द्वारा उल्लिखित कीवर्ड वास्तव में लागू किया गया था, तो हम boxed MyNamespace.MyTypeMyNamespace.MyType नामक मूल्य प्रकार वर्ग परिभाषा के बॉक्सिंग प्रकार को निर्दिष्ट करने के लिए उपयोग करने में सक्षम होंगे ।

तो, .method static void Print(valuetype MyNamespace.MyType test) cil managedमूल्य प्रकार वर्ग परिभाषा द्वारा परिभाषित मूल्य प्रकार लेता है MyNamespace.MyType, जिसका नाम है ,

जबकि .method static void Print(class MyNamespace.MyType test) cil managedऑब्जेक्ट प्रकार वर्ग परिभाषा द्वारा परिभाषित ऑब्जेक्ट प्रकार नाम लेता है MyNamespace.MyType

इसी तरह यदि boxedकोई कीवर्ड था, .method static void Print(boxed MyNamespace.MyType test) cil managedतो नामांकित वर्ग परिभाषा द्वारा परिभाषित मूल्य प्रकार का बॉक्सिंग प्रकार ले जाएगा MyNamespace.MyType

फिर आप किसी भी अन्य ऑब्जेक्ट प्रकार की तरह बॉक्सिंग प्रकार को तुरंत सक्षम कर सकते हैं और इसे किसी भी विधि के पास पास कर सकते हैं System.ValueType, जो एक तर्क के रूप में objectया boxed MyNamespace.MyValueTypeएक तर्क के रूप में लेता है , और यह सभी अन्य उद्देश्यों और उद्देश्यों के लिए, किसी अन्य संदर्भ प्रकार की तरह काम करेगा। यह एक मूल्य प्रकार नहीं है, लेकिन मूल्य के प्रकार के संबंधित बॉक्सिंग प्रकार है।

 

सारांश

तो, सारांश में, और प्रश्न का उत्तर देने के लिए:

मान प्रकार संदर्भ प्रकार नहीं हैं और किसी अन्य प्रकार से इनहेरिट नहीं करते हैंSystem.ValueType , और वे इंटरफ़ेस को लागू नहीं कर सकते हैं । संबंधित बॉक्स प्रकार जो भी परिभाषित किए गए हैं वे इनहेरिट करते हैंSystem.ValueType और इंटरफेस को लागू कर सकते हैं

एक .classपरिभाषा परिस्थिति के आधार पर विभिन्न चीजों को परिभाषित करती है।

  • यदि interfaceशब्दार्थ विशेषता निर्दिष्ट की जाती है, तो वर्ग परिभाषा एक अंतरफलक को परिभाषित करती है।
  • यदि interfaceशब्दार्थ गुण निर्दिष्ट नहीं है, और परिभाषा विस्तार नहीं करती है System.ValueType, तो वर्ग परिभाषा एक वस्तु प्रकार (वर्ग) को परिभाषित करती है।
  • यदि interfaceसिमेंटिक विशेषता निर्दिष्ट नहीं है, और परिभाषा का विस्तार होता है System.ValueType, तो वर्ग परिभाषा एक मूल्य प्रकार और उसके संबंधित बॉक्सिंग प्रकार (संरचना) को परिभाषित करती है ।

मेमोरी लेआउट

यह खंड 32-बिट प्रक्रिया मानता है

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

public struct MyStruct
{
    public int A;
    public short B;
    public int C;
}

यदि हम कल्पना करते हैं कि MyStruct का एक उदाहरण 0x1000 पते पर आवंटित किया गया था, तो यह मेमोरी लेआउट है:

0x1000: int A;
0x1004: short B;
0x1006: 2 byte padding
0x1008: int C;

अनुक्रमिक लेआउट के लिए डिफ़ॉल्ट डिफ़ॉल्ट। फ़ील्ड्स अपने स्वयं के आकार की सीमाओं पर गठबंधन किए जाते हैं। इसे संतुष्ट करने के लिए पैडिंग को जोड़ा जाता है।

 

यदि हम एक कक्षा को ठीक उसी तरह परिभाषित करते हैं, जैसे:

public class MyClass
{
    public int A;
    public short B;
    public int C;
}

उसी पते की कल्पना करते हुए, मेमोरी लेआउट इस प्रकार है:

0x1000: Pointer to object header
0x1004: int A;
0x1008: int C;
0x100C: short B;
0x100E: 2 byte padding
0x1010: 4 bytes extra

कक्षाएं स्वचालित लेआउट के लिए डिफ़ॉल्ट होती हैं, और जेआईटी कंपाइलर उन्हें सबसे इष्टतम क्रम में व्यवस्थित करेंगे। फ़ील्ड्स अपने स्वयं के आकार की सीमाओं पर गठबंधन किए जाते हैं। इसे संतुष्ट करने के लिए पैडिंग को जोड़ा जाता है। मुझे यकीन नहीं है कि क्यों, लेकिन हर वर्ग के अंत में एक अतिरिक्त 4 बाइट्स होती हैं।

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

इस प्रकार, मूल्य प्रकार विरासत, इंटरफेस और न ही बहुरूपता का समर्थन नहीं करते हैं।

तरीके

मान प्रकार में वर्चुअल विधि तालिकाएँ नहीं होती हैं, और इस प्रकार बहुरूपता का समर्थन नहीं करते हैं। हालाँकि , उनके संबंधित बॉक्सिंग प्रकार करता है

यदि आप एक struct का एक उदाहरण है और की तरह एक आभासी विधि कॉल करने का प्रयास करते हैं ToString()पर परिभाषित System.Object, क्रम struct बॉक्स करने के है।

MyStruct myStruct = new MyStruct();
Console.WriteLine(myStruct.ToString()); // ToString() call causes boxing of MyStruct.

हालाँकि, यदि संरचना ओवरराइड होती है, ToString()तो कॉल स्टेटिक रूप से बाध्य हो जाएगा और रनटाइम MyStruct.ToString()बॉक्सिंग के बिना और किसी भी वर्चुअल मेथड टेबल में देखे बिना कॉल करेगा (स्ट्रक्चर्स के पास कोई नहीं है)। इस कारण से, यह ToString()कॉल को इनलाइन करने में भी सक्षम है ।

यदि संरचना ओवरराइड होती है ToString()और बॉक्सिंग होती है, तो वर्चुअल विधि तालिका का उपयोग करके कॉल को हल किया जाएगा।

System.ValueType myStruct = new MyStruct(); // Creates a new instance of the boxed type of MyStruct.
Console.WriteLine(myStruct.ToString()); // ToString() is now called through the virtual method table.

हालांकि, याद रखें कि ToString()संरचना में परिभाषित किया गया है, और इस प्रकार संरचना मूल्य पर संचालित होता है, इसलिए यह एक मूल्य प्रकार की अपेक्षा करता है। किसी अन्य वर्ग की तरह, बॉक्सिंग प्रकार में ऑब्जेक्ट हेडर होता है। अगर ToString()विधि struct पर परिभाषित में बॉक्स्ड प्रकार के साथ सीधे बुलाया गया था thisसूचक, जब पहुँच क्षेत्र की कोशिश Aमें MyStructहै, यह ऑफसेट 0, जो बॉक्स्ड प्रकार में वस्तु हैडर सूचक होगा पहुंच जाएगा। तो बॉक्सिंग प्रकार में एक छिपी हुई विधि है जो वास्तविक ओवरराइडिंग करती है ToString()। यह छिपा हुआ तरीका अनबॉक्स (केवल unboxआईएल इंस्ट्रक्शन की तरह पता गणना ) बॉक्सिंग प्रकार फिर सांख्यिकीय ToString()रूप से संरचना पर परिभाषित कहता है ।

इसी तरह, बॉक्सिंग प्रकार में प्रत्येक कार्यान्वित इंटरफ़ेस विधि के लिए एक छिपी हुई विधि होती है जो समान अनबॉक्सिंग करती है और फिर संरचनात्मक रूप से परिभाषित विधि को कॉल करती है।

 

सीएलआई विनिर्देश

मुक्केबाज़ी

I.8.2.4 प्रत्येक मूल्य प्रकार के लिए, CTS एक संबंधित संदर्भ प्रकार को परिभाषित करता है जिसे बॉक्सिंग प्रकार कहा जाता है। रिवर्स सच नहीं है: सामान्य तौर पर, संदर्भ प्रकारों में एक समान मूल्य प्रकार नहीं होता है। एक बॉक्सिंग प्रकार (एक बॉक्सिंग मूल्य) के मूल्य का प्रतिनिधित्व एक ऐसा स्थान है जहां मूल्य प्रकार के मूल्य को संग्रहीत किया जा सकता है। एक बॉक्सिंग प्रकार एक ऑब्जेक्ट प्रकार है और एक बॉक्सिंग मूल्य एक ऑब्जेक्ट है।

मूल्य प्रकारों को परिभाषित करना

I.8.9.7 वर्ग परिभाषा द्वारा परिभाषित सभी प्रकार वस्तु प्रकार नहीं हैं (देखें .2I.8.2.3); विशेष रूप से, मूल्य प्रकार ऑब्जेक्ट प्रकार नहीं होते हैं, लेकिन उन्हें एक वर्ग परिभाषा का उपयोग करके परिभाषित किया जाता है। मान प्रकार के लिए एक वर्ग परिभाषा दोनों (अनबॉक्स) मान प्रकार और संबंधित बॉक्सिंग प्रकार (.4I.8.8.4 देखें) को परिभाषित करती है। वर्ग परिभाषा के सदस्य दोनों के प्रतिनिधित्व को परिभाषित करते हैं।

II.10.1.3 प्रकार के शब्दार्थ गुण निर्दिष्ट करते हैं कि क्या कोई इंटरफ़ेस, वर्ग या मान प्रकार परिभाषित किया जाएगा। इंटरफ़ेस विशेषता एक इंटरफ़ेस निर्दिष्ट करती है। यदि यह विशेषता मौजूद नहीं है और परिभाषा फैली हुई है (प्रत्यक्ष या अप्रत्यक्ष रूप से) System.ValueType, और परिभाषा System.Enum के लिए नहीं है, तो एक मान प्रकार परिभाषित किया जाएगा (.1II.13)। अन्यथा, एक वर्ग परिभाषित किया जाएगा (.11II.11)।

मूल्य प्रकार विरासत में नहीं मिलते हैं

I.8.9.10 उनके अनबॉक्स्ड फॉर्म में मूल्य प्रकार किसी भी प्रकार से प्राप्त नहीं होते हैं। बॉक्स किए गए मूल्य प्रकार सीधे System.ValueType से इनहेरिट करेंगे जब तक कि वे एन्यूमरेशन नहीं होते हैं, इस स्थिति में, वे System.Enum से वारिस होंगे। बॉक्सिंग मूल्य प्रकारों को सील किया जाएगा।

II.13 अनबॉक्स किए गए मान प्रकारों को किसी अन्य प्रकार के उपप्रकार नहीं माना जाता है और यह अनबॉक्स किए गए मान प्रकारों पर आइंस्टीन निर्देश (विभाजन III देखें) का उपयोग करने के लिए मान्य नहीं है। आइंस्टीन निर्देश का उपयोग बॉक्सिंग मूल्य प्रकारों के लिए किया जा सकता है, हालांकि।

I.8.9.10 एक मान प्रकार इनहेरिट नहीं करता है; वर्ग परिभाषा में निर्दिष्ट आधार प्रकार, बॉक्स प्रकार के आधार प्रकार को परिभाषित करता है।

मूल्य प्रकार इंटरफेस को लागू नहीं करते हैं

I.8.9.7 मान प्रकार इंटरफ़ेस अनुबंधों का समर्थन नहीं करते हैं, लेकिन उनके संबद्ध बॉक्सिंग प्रकार करते हैं।

II.13 मान प्रकार शून्य या अधिक इंटरफ़ेस लागू करेंगे, लेकिन इसका अर्थ केवल उनके बॉक्सिंग रूप में है (.1II.13.3)।

I.8.2.4 इंटरफेस और वंशानुक्रम केवल संदर्भ प्रकारों पर परिभाषित किए गए हैं। इस प्रकार, जबकि एक मूल्य प्रकार की परिभाषा (§I.8.9.7) उन दोनों इंटरफेस को निर्दिष्ट कर सकती है जिन्हें मूल्य प्रकार और वर्ग (System.ValueType या System.Enum) से लागू किया जा सकता है, जहां से यह विरासत में मिलता है, ये केवल बॉक्सिंग मूल्यों पर लागू होते हैं ।

गैर-मौजूद बॉक्सिंग कीवर्ड

II.13.1 एक वैल्यू टाइप का अनबॉक्स्ड फॉर्म एक प्रकार के रेफरेंस के बाद वैल्यूएटाइप कीवर्ड का उपयोग करके संदर्भित किया जाएगा। एक प्रकार के संदर्भ के बाद एक मूल्य प्रकार के बॉक्सिंग फार्म का संदर्भ बॉक्सिंग कीवर्ड का उपयोग करके किया जाएगा।

नोट: यहां विनिर्देश गलत है, कोई boxedकीवर्ड नहीं है ।

उपसंहार

मुझे लगता है कि मूल्य प्रकार विरासत में कैसे लगते हैं, इस भ्रम का एक हिस्सा है, इस तथ्य से उपजा है कि सी # बॉक्सिंग और अनबॉक्सिंग करने के लिए कास्टिंग सिंटैक्स का उपयोग करता है, जिससे ऐसा लगता है कि आप कलाकारों का प्रदर्शन कर रहे हैं, जो वास्तव में मामला नहीं है (हालांकि, CLR एक InvalidCastException को फेंक देगा यदि गलत प्रकार को अनबॉक्स करने का प्रयास किया जा रहा है)। (object)myStructC # में मूल्य प्रकार के बॉक्सिंग प्रकार का एक नया उदाहरण बनाता है; यह किसी भी जाति का प्रदर्शन नहीं करता है। इसी तरह, (MyStruct)objसी # में एक बॉक्सिंग प्रकार को अनबॉक्स किया जाता है, मान भाग को कॉपी करके; यह किसी भी जाति का प्रदर्शन नहीं करता है।


1
अंत में, एक उत्तर जो स्पष्ट रूप से वर्णन करता है कि यह कैसे काम करता है! यह एक स्वीकृत उत्तर होने के योग्य है। बहुत बढ़िया!
बस शैडो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.