हमें C # में बॉक्सिंग और अनबॉक्सिंग की आवश्यकता क्यों है?


323

हमें C # में बॉक्सिंग और अनबॉक्सिंग की आवश्यकता क्यों है?

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

short s = 25;

object objshort = s;  //Boxing

short anothershort = (short)objshort;  //Unboxing

जवाबों:


480

क्यों

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

इसके बारे में इस तरह से सोचें। आपके पास एक oप्रकार का चर है object। और अब आपके पास एक है intऔर आप इसे डालना चाहते हैं ooकहीं न कहीं एक संदर्भ है, और कहीं से किसी चीज का संदर्भ intनहीं है (आखिरकार, यह सिर्फ एक संख्या है)। तो, आप यह क्या करते हैं: आप एक नया बनाते हैं जो objectस्टोर कर सकता है intऔर फिर आप उस ऑब्जेक्ट का एक संदर्भ निर्दिष्ट करते हैं o। हम इस प्रक्रिया को "मुक्केबाजी" कहते हैं।

इसलिए, यदि आप एक एकीकृत प्रकार की प्रणाली होने के बारे में परवाह नहीं करते हैं (यानी, संदर्भ प्रकार और मूल्य प्रकार में बहुत भिन्न प्रतिनिधित्व हैं और आप दोनों को "प्रतिनिधित्व" करने के लिए एक सामान्य तरीका नहीं चाहते हैं) तो आपको मुक्केबाजी की आवश्यकता नहीं है। यदि आपको intउनके अंतर्निहित मूल्य का प्रतिनिधित्व करने के बारे में परवाह नहीं है (यानी, इसके बजाय intसंदर्भ प्रकार भी हैं और बस उनके अंतर्निहित मूल्य का संदर्भ संग्रहीत करें) तो आपको मुक्केबाजी की आवश्यकता नहीं है।

मुझे इसका उपयोग कहां करना चाहिए

उदाहरण के लिए, पुराना संग्रह प्रकार ArrayListकेवल खाता है object। यही है, यह केवल उन चीज़ों के संदर्भों को संग्रहीत करता है जो कहीं रहते हैं। मुक्केबाजी के बिना आप intइस तरह के संग्रह में नहीं डाल सकते । लेकिन बॉक्सिंग के साथ, आप कर सकते हैं।

अब, जेनेरिक के दिनों में आपको वास्तव में इसकी आवश्यकता नहीं है और आम तौर पर इस मुद्दे के बारे में सोचने के बिना आसानी से जा सकते हैं। लेकिन इसके बारे में पता करने के लिए कुछ चेतावनी हैं:

यह सही है:

double e = 2.718281828459045;
int ee = (int)e;

यह नहीं है:

double e = 2.718281828459045;
object o = e; // box
int ee = (int)o; // runtime exception

इसके बजाय आपको यह करना चाहिए:

double e = 2.718281828459045;
object o = e; // box
int ee = (int)(double)o;

पहले हमें स्पष्ट रूप से अनबॉक्स double( (double)o) करना होगा और फिर उसको कास्ट करना होगा int

निम्नलिखित का परिणाम क्या है:

double e = 2.718281828459045;
double d = e;
object o1 = d;
object o2 = e;
Console.WriteLine(d == e);
Console.WriteLine(o1 == o2);

अगले वाक्य पर जाने से पहले एक सेकंड के लिए इसके बारे में सोचें।

अगर आपने कहा Trueऔर Falseमहान! रुको क्या? ऐसा इसलिए है क्योंकि ==संदर्भ प्रकार संदर्भ-समानता का उपयोग करता है जो यह जांचता है कि संदर्भ समान हैं या नहीं, यदि अंतर्निहित मान समान हैं। यह एक खतरनाक आसान गलती है। शायद और भी सूक्ष्म

double e = 2.718281828459045;
object o1 = e;
object o2 = e;
Console.WriteLine(o1 == o2);

भी छापेंगे False!

कहने के लिए बेहतर है:

Console.WriteLine(o1.Equals(o2));

जो तब, आभार, प्रिंट होगा True

एक अंतिम सूक्ष्मता:

[struct|class] Point {
    public int x, y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
}

Point p = new Point(1, 1);
object o = p;
p.x = 2;
Console.WriteLine(((Point)o).x);

आउटपुट क्या है? निर्भर करता है! यदि Pointएक है structतो आउटपुट है, 1लेकिन अगर Pointहै classतो आउटपुट है 2! एक बॉक्सिंग रूपांतरण व्यवहार में अंतर को स्पष्ट करते हुए बॉक्सिंग किए जा रहे मूल्य की एक प्रति बनाता है।


@ जेसन क्या आपके कहने का मतलब है कि यदि हमारे पास आदिम सूचियाँ हैं, तो किसी भी बॉक्सिंग / अनबॉक्सिंग का उपयोग करने का कोई कारण नहीं है?
पेसरियर

मुझे यकीन नहीं है कि आप "आदिम सूची" से क्या मतलब है।
जेसन

3
आप के प्रदर्शन प्रभाव से बात करें, कर सकते हैं boxingऔर unboxing?
केविन मेरेडिथ


2
उत्कृष्ट उत्तर - सबसे अधिक स्पष्टीकरण से बेहतर मैंने अच्छी तरह से मानी जाने वाली पुस्तकों में पढ़ा है।
फ्रेडएम

58

.NET फ्रेमवर्क में, दो प्रकार की प्रजातियां हैं - मूल्य प्रकार और संदर्भ प्रकार। यह OO भाषाओं में अपेक्षाकृत सामान्य है।

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

अब, पुराने दिनों में वापस (Microsoft.NET के 1.0), वहाँ इस नए पीढ़ी के hullabaloo नहीं थे। आप एक ऐसा तरीका नहीं लिख सकते हैं जिसमें एक एकल तर्क हो जो एक मूल्य प्रकार और एक संदर्भ प्रकार की सेवा कर सके। यह बहुरूपता का उल्लंघन है। तो बॉक्सिंग को एक वस्तु में एक मूल्य प्रकार के लिए मजबूर करने के साधन के रूप में अपनाया गया था।

यदि यह संभव नहीं था, तो ढांचा उन तरीकों और वर्गों से भरा होगा, जिनका एकमात्र उद्देश्य अन्य प्रकार की प्रजातियों को स्वीकार करना था। इतना ही नहीं, लेकिन चूंकि मूल्य प्रकार वास्तव में एक सामान्य प्रकार के पूर्वजों को साझा नहीं करते हैं, इसलिए आपके पास प्रत्येक मूल्य प्रकार (बिट, बाइट, int16, int32, आदि) के लिए एक अलग विधि अधिभार होना चाहिए।

बॉक्सिंग ने ऐसा होने से रोका। और इसीलिए अंग्रेज बॉक्सिंग डे मनाते हैं।


1
जेनरिक से पहले, ऑटो-बॉक्सिंग कई चीजें करने के लिए आवश्यक था; हालांकि, जेनरिक के अस्तित्व को देखते हुए, यह पुराने कोड के साथ संगतता बनाए रखने की आवश्यकता के लिए नहीं था, मुझे लगता है कि निहित बॉक्सिंग रूपांतरणों के बिना नेट बेहतर होगा। की तरह एक मान प्रकार कास्टिंग List<string>.Enumeratorके लिए IEnumerator<string>पैदावार एक वस्तु है जो ज्यादातर एक वर्ग प्रकार की तरह बर्ताव करता है, लेकिन एक टूट के साथ Equalsविधि। कस्टम रूपांतरण ऑपरेटर को कॉल List<string>.Enumeratorकरने के लिए कास्ट करने का एक बेहतर तरीका है IEnumerator<string>, लेकिन निहित रूपांतरण के अस्तित्व को रोकता है।
सुपरकट

42

इसे समझने का सबसे अच्छा तरीका है कि निम्न-स्तरीय प्रोग्रामिंग भाषाओं को C # बनाया जाए।

सी जैसी निम्नतम-स्तरीय भाषाओं में, सभी चर एक स्थान पर जाते हैं: स्टैक। हर बार जब आप एक वैरिएबल घोषित करते हैं तो वह स्टैक पर चला जाता है। वे केवल आदिम मूल्य हो सकते हैं, जैसे कि एक बूल, एक बाइट, एक 32-बिट इंट, 32-बिट यूंट, आदि। स्टैक सरल और तेज दोनों है। जैसा कि चर जोड़े जाते हैं, वे बस एक दूसरे के ऊपर जाते हैं, इसलिए पहले आप घोषणा करते हैं, 0x00, अगला 0x01 पर, अगला 0x02 RAM में, आदि। इसके अलावा, चर अक्सर संकलन पर पूर्व-संबोधित होते हैं- समय, इसलिए उनका पता कार्यक्रम चलाने से पहले ही पता चल जाता है।

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

संकेत से निपटना कठिन है। वे मेमोरी लीक, बफर ओवररन और फ्रस्ट्रेशन का कारण हैं। बचाव के लिए सी #।

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

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

bool b = false; // Cheap, on Stack
object o = b; // Legal, easy to code, but complex - Boxing!
bool b2 = (bool)o; // Unboxing!

मुक्केबाजी के लाभ का एक मजबूत चित्रण शून्य के लिए एक जाँच है:

if (b == null) // Will not compile - bools can't be null
if (o == null) // Will compile and always return false

हमारे ऑब्जेक्ट ओ स्टैक में तकनीकी रूप से एक पता है जो हमारे बूल बी की एक प्रति को इंगित करता है, जिसे हीप में कॉपी किया गया है। हम n को n के लिए o चेक कर सकते हैं क्योंकि बूल बॉक्सेड है और वहां रखा गया है।

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

ऐतिहासिक सी # संरचनाओं की एक गैर-संपूर्ण सूची जिसमें बॉक्सिंग की आवश्यकता होती है, जिससे आपको बचना चाहिए:

  • ईवेंट सिस्टम यह बताता है कि इसके भोलेपन में रेस की स्थिति है, और यह एसिंक्स का समर्थन नहीं करता है। बॉक्सिंग समस्या में जोड़ें और इसे शायद टाला जाना चाहिए। (आप इसे एक एस्कॉन इवेंट सिस्टम के साथ उदाहरण के लिए बदल सकते हैं जो जेनरिक का उपयोग करता है।)

  • पुराने थ्रेडिंग और टाइमर मॉडल ने अपने मापदंडों पर एक बॉक्स को मजबूर किया, लेकिन इसे async / प्रतीक्षित द्वारा प्रतिस्थापित किया गया है जो कि दूर के क्लीनर और अधिक कुशल हैं।

  • .Net 1.1 संग्रह पूरी तरह से बॉक्सिंग पर निर्भर था, क्योंकि वे जेनरिक से पहले आए थे। ये अभी भी System.Collections में घूम रहे हैं। किसी भी नए कोड में आपको System.Collections.Generic से संग्रह का उपयोग करना चाहिए, जो बॉक्सिंग से बचने के अलावा आपको मजबूत प्रकार की सुरक्षा भी प्रदान करता है

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

नीचे मिकेल के सुझाव:

यह करो

using System.Collections.Generic;

var employeeCount = 5;
var list = new List<int>(10);

यह नहीं

using System.Collections;

Int32 employeeCount = 5;
var list = new ArrayList(10);

अपडेट करें

यह जवाब मूल रूप से Int32, बूल आदि के मुक्केबाजी का कारण बनता है, जब वास्तव में वे वैल्यू टाइप के लिए साधारण उपनाम हैं। यही है, .Net के पास बिना किसी कार्यात्मक अंतर के, बूल, Int32, स्ट्रिंग और C # उपनामों के प्रकार हैं जो उन्हें बूल, int, string में बदल देते हैं।


4
आपने मुझे सिखाया कि सौ प्रोग्रामर और आईटी-प्रोफेशनल्स वर्षों में क्या समझा सकते हैं, लेकिन यह कहने के लिए कि आपको क्या करना चाहिए इसके बजाय इसे बदलना चाहिए , क्योंकि इसका पालन करना थोड़ा कठिन था .. ग्राउंड रूल्स सबसे अधिक बार नहीं होते 1 , आप ऐसा नहीं करेंगे, इसके बजाय यह करें
मिकेल पुसारी

2
इस उत्तर को सौ बार ANSWER के रूप में चिह्नित किया जाना चाहिए था!
पौयन

3
c # में कोई "Int" नहीं है, int और Int32 है। मेरा मानना ​​है कि आप एक बताते हुए गलत हैं एक मूल्य प्रकार है और दूसरा एक संदर्भ प्रकार है जो मूल्य प्रकार को लपेटता है। जब तक मैं गलत नहीं हूँ, यह जावा में सच है, लेकिन सी # नहीं। C # में, जो IDE में नीला दिखाई देता है, उनकी संरचना परिभाषा के लिए उपनाम हैं। तो: int = Int32, बूल = बूलियन, स्ट्रिंग = स्ट्रिंग। बूलियन से अधिक बूल का उपयोग करने का कारण यह है कि एमएसडीएन डिजाइन दिशानिर्देशों और सम्मेलनों में ऐसा सुझाया गया है। नहीं तो मुझे यह जवाब पसंद है। लेकिन जब तक आप मुझे गलत साबित नहीं करेंगे या आपके जवाब में इसे ठीक नहीं करेंगे, तब तक मैं वोट डाल दूंगा।
हेरिबेटो लुगो

2
यदि आप एक चर को int के रूप में और दूसरे को Int32, या बूल और बूलियन के रूप में घोषित करते हैं - राइट क्लिक और व्यू परिभाषा, तो आप एक संरचना के लिए एक ही परिभाषा में समाप्त हो जाएंगे।
हेरिबेटो लुगो

2
@HeribertoLugo सही है, लाइन "आपको अपने मूल्य प्रकारों को बूल के बजाय बूल घोषित करने से बचना चाहिए" गलत है। ओपी बताते हैं कि आपको अपने बूल (या बूलियन, या किसी अन्य मूल्य-प्रकार) को वस्तु के रूप में घोषित करने से बचना चाहिए। बूल / बूलियन, int / Int32, सिर्फ C # और .NET के बीच उपनाम हैं: docs.microsoft.com/en-us/dotnet/csharp/language-reference/…
STW

21

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

अब सामान्य संग्रह का उपयोग करना, यह बहुत दूर चला जाता है। यदि आप एक बनाते हैं List<int>, तो कोई बॉक्सिंग नहीं किया जाता है - List<int>पूर्णांकों को सीधे पकड़ सकता है।


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

1
यह सच है - यह ADO.NET में भी हर समय दिखाई देता है - sql पैरामीटर मान सभी 'ऑब्जेक्ट का कोई फर्क नहीं पड़ता कि वास्तविक डेटा प्रकार क्या है
Ray

11

बॉक्सिंग और अनबॉक्सिंग का उपयोग विशेष रूप से मूल्य-प्रकार की वस्तुओं को संदर्भ-प्रकार के रूप में करने के लिए किया जाता है; उनके वास्तविक मूल्य को प्रबंधित ढेर तक ले जाना और संदर्भ द्वारा उनके मूल्य तक पहुंचना।

बॉक्सिंग और अनबॉक्सिंग के बिना आप संदर्भ द्वारा मूल्य-प्रकार कभी भी पारित नहीं कर सकते; और इसका मतलब है कि आप ऑब्जेक्ट के उदाहरणों के रूप में मूल्य-प्रकार पारित नहीं कर सकते हैं।


अभी भी लगभग 10 साल बाद अच्छा जवाब सर +1
एसएन

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

8

आखिरी जगह मुझे कुछ अनबॉक्स करना था जब कुछ कोड लिख रहे थे जो एक डेटाबेस से कुछ डेटा को पुनर्प्राप्त करता था (मैं LINQ से SQL का उपयोग नहीं कर रहा था , बस सादे पुराने ADO.NET ):

int myIntValue = (int)reader["MyIntValue"];

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


4

बॉक्सिंग की आवश्यकता तब होती है, जब हमारे पास एक फ़ंक्शन होता है जिसे एक पैरामीटर के रूप में ऑब्जेक्ट की आवश्यकता होती है, लेकिन हमारे पास अलग-अलग मूल्य प्रकार होते हैं जिन्हें पारित करने की आवश्यकता होती है, उस स्थिति में हमें फ़ंक्शन को पास करने से पहले मूल्य प्रकारों को ऑब्जेक्ट प्रकारों में परिवर्तित करने की आवश्यकता होती है।

मुझे नहीं लगता कि यह सच है, इसके बजाय यह प्रयास करें:

class Program
    {
        static void Main(string[] args)
        {
            int x = 4;
            test(x);
        }

        static void test(object o)
        {
            Console.WriteLine(o.ToString());
        }
    }

यह ठीक चलता है, मैंने बॉक्सिंग / अनबॉक्सिंग का उपयोग नहीं किया। (जब तक कि कंपाइलर पर्दे के पीछे न हो?)


ऐसा इसलिए है क्योंकि सब कुछ System.Object से विरासत में मिला है, और आप विधि को अतिरिक्त जानकारी के साथ एक वस्तु दे रहे हैं, इसलिए मूल रूप से आप परीक्षण विधि को बुला रहे हैं कि यह क्या उम्मीद कर रहा है और कुछ भी उम्मीद कर सकता है क्योंकि यह विशेष रूप से कुछ भी उम्मीद नहीं करता है। .NET में बहुत कुछ दृश्यों के पीछे किया जाता है, और इसका उपयोग करने के लिए एक बहुत ही सरल भाषा है, इसका कारण है
Mikael Puusaari

1

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


0

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

यह किसी भी तरीके के लिए सही है जो objectएक पैरामीटर के रूप में लिया जाता है - इसके लिए एक संदर्भ प्रकार होना चाहिए।


0

सामान्य तौर पर, आप आमतौर पर अपने मूल्य प्रकारों को बॉक्सिंग से बचना चाहेंगे।

हालांकि, दुर्लभ घटनाएं हैं जहां यह उपयोगी है। यदि आपको 1.1 रूपरेखा को लक्षित करने की आवश्यकता है, उदाहरण के लिए, आपके पास सामान्य संग्रह तक पहुंच नहीं होगी। .NET 1.1 में संग्रह के किसी भी उपयोग को आपके मान प्रकार को System.Object के रूप में व्यवहार करना होगा, जो बॉक्सिंग / अनबॉक्सिंग का कारण बनता है।

.NET 2.0+ में इसके उपयोगी होने के लिए अभी भी मामले हैं। किसी भी समय आप इस तथ्य का लाभ उठाना चाहते हैं कि मूल्य प्रकार सहित सभी प्रकारों को सीधे एक वस्तु के रूप में माना जा सकता है, आपको बॉक्सिंग / अनबॉक्सिंग का उपयोग करने की आवश्यकता हो सकती है। यह कई बार आसान हो सकता है, क्योंकि यह आपको एक संग्रह में किसी भी प्रकार को सहेजने की अनुमति देता है (जेनेरिक संग्रह में टी के बजाय ऑब्जेक्ट का उपयोग करके), लेकिन सामान्य तौर पर, इससे बचने के लिए बेहतर है, क्योंकि आप टाइप सुरक्षा खो रहे हैं। एक मामला जहां अक्सर बॉक्सिंग होती है, हालांकि, जब आप रिफ्लेक्शन का उपयोग कर रहे हैं - प्रतिबिंब में कई कॉलों को मूल्य प्रकार के साथ काम करते समय बॉक्सिंग / अनबॉक्सिंग की आवश्यकता होगी, क्योंकि प्रकार पहले से ज्ञात नहीं है।


0

बॉक्सिंग ढेर पर एक वस्तु में कुछ ऑफसेट पर डेटा के साथ एक संदर्भ प्रकार के लिए मूल्य का रूपांतरण है।

मुक्केबाजी वास्तव में क्या करती है। यहाँ कुछ उदाहरण हैं

मोनो सी ++

void* mono_object_unbox (MonoObject *obj)
 {    
MONO_EXTERNAL_ONLY_GC_UNSAFE (void*, mono_object_unbox_internal (obj));
 }

#define MONO_EXTERNAL_ONLY_GC_UNSAFE(t, expr) \
    t result;       \
    MONO_ENTER_GC_UNSAFE;   \
    result = expr;      \
    MONO_EXIT_GC_UNSAFE;    \
    return result;

static inline gpointer
mono_object_get_data (MonoObject *o)
{
    return (guint8*)o + MONO_ABI_SIZEOF (MonoObject);
}

#define MONO_ABI_SIZEOF(type) (MONO_STRUCT_SIZE (type))
#define MONO_STRUCT_SIZE(struct) MONO_SIZEOF_ ## struct
#define MONO_SIZEOF_MonoObject (2 * MONO_SIZEOF_gpointer)

typedef struct {
    MonoVTable *vtable;
    MonoThreadsSync *synchronisation;
} MonoObject;

मोनो में अनबॉक्सिंग ऑब्जेक्ट में 2 गॉइंटर्स की ऑफसेट पर सूचक को कास्टिंग करने की एक प्रक्रिया है (उदाहरण के लिए 16 बाइट्स)। ए gpointerहै ए void*। जब MonoObjectयह स्पष्ट रूप से डेटा के लिए सिर्फ एक हेडर की परिभाषा को देखते हुए समझ में आता है ।

सी ++

C ++ में एक मान बॉक्स करने के लिए आप कुछ ऐसा कर सकते हैं:

#include <iostream>
#define Object void*

template<class T> Object box(T j){
  return new T(j);
}

template<class T> T unbox(Object j){
  T temp = *(T*)j;
  delete j;
  return temp;
}

int main() {
  int j=2;
  Object o = box(j);
  int k = unbox<int>(o);
  std::cout << k;
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.