कुल मिलाकर:
अक्सर आप इस बात पर भरोसा नहीं कर सकते हैं कि किसी फ़ंक्शन का चर किस प्रकार का उपभोग करेगा, इसलिए आपको एक ऑब्जेक्ट चर का उपयोग करने की आवश्यकता होती है जो सबसे कम आम भाजक - .Net में इसका विस्तार होता है object
।
हालांकि object
एक वर्ग है और अपनी सामग्री को संदर्भ के रूप में संग्रहीत करता है।
List<int> notBoxed = new List<int> { 1, 2, 3 };
int i = notBoxed[1]; // this is the actual value
List<object> boxed = new List<object> { 1, 2, 3 };
int j = (int) boxed[1]; // this is an object that can be 'unboxed' to an int
जबकि ये दोनों समान जानकारी रखते हैं दूसरी सूची बड़ी और धीमी है। दूसरी सूची में प्रत्येक मूल्य वास्तव में एक का एक संदर्भ है object
जो धारण करता है int
।
इसे बॉक्सिंग कहा जाता है क्योंकि int
यह लिपटे हुए है object
। जब इसकी कास्ट बैक int
अनबॉक्स हो जाती है - तो इसे वापस वैल्यू में बदल दिया जाता है।
मान प्रकारों के लिए (अर्थात सभी structs
) यह धीमा है, और संभावित रूप से बहुत अधिक स्थान का उपयोग करता है।
संदर्भ प्रकारों (यानी सभी classes
) के लिए यह एक समस्या से काफी कम है, क्योंकि वे एक संदर्भ के रूप में वैसे भी संग्रहीत हैं।
एक बॉक्सेड वैल्यू टाइप के साथ एक और समस्या यह है कि यह स्पष्ट नहीं है कि आप बॉक्स के साथ काम कर रहे हैं, बल्कि मूल्य के बजाय। जब आप दो की तुलना structs
करते हैं तो आप मूल्यों की तुलना कर रहे हैं, लेकिन जब आप दो की तुलना करते हैं classes
(तब डिफ़ॉल्ट रूप से) आप संदर्भ की तुलना कर रहे हैं - यानी ये वही उदाहरण हैं?
बॉक्सिंग मूल्य प्रकारों के साथ काम करते समय यह भ्रामक हो सकता है:
int a = 7;
int b = 7;
if(a == b) // Evaluates to true, because a and b have the same value
object c = (object) 7;
object d = (object) 7;
if(c == d) // Evaluates to false, because c and d are different instances
आसपास काम करना आसान है:
if(c.Equals(d)) // Evaluates to true because it calls the underlying int's equals
if(((int) c) == ((int) d)) // Evaluates to true once the values are cast
हालाँकि यह एक और बात है कि बॉक्सिंग वैल्यू से निपटते समय सावधान रहना चाहिए।