2010-10-26 18 views
6

निम्नलिखित ::अनबॉक्सिंग एनम्स क्यों अजीब परिणाम उत्पन्न करता है?

Object box = 5; 
int @int = (int)box; // int = 5 
int? nullableInt = box as int?; // nullableInt = 5; 
StringComparison @enum = (StringComparison)box; // enum = OrdinalIgnoreCase 
StringComparison? nullableEnum = box as StringComparison?; // nullableEnum = null. 

2 बातें ::

  1. मैं StringComparison को क्यों Unbox कर सकते हैं पर विचार करें? मुझे लगता है कि ऐसा इसलिए है क्योंकि यह अंतर्निहित प्रकार Int32 है लेकिन मुझे अभी भी यह अजीब लगता है।
  2. nullableEnum क्यों शून्य का मूल्य है?

जैसा कि मैं समझता हूं कि एकमात्र मान्य अनबॉक्सिंग बॉक्स किए गए मान प्रकार से है, यह प्रकार या नालीबल प्रकार के लिए है। यदि intEnum पर अनबॉक्स कर सकता है, तो शून्य के मूल्यों के लिए समान क्यों नहीं है? इसी तरह, अगर 5 के बजाय मैंने StringComparison.OrdinalIgnoreCase बॉक्स किया, तो यह होगा कि nullableInt शून्य होगा, लेकिन nullableEnum नहीं होगा।

उत्तर

2

सच पूछिये तो मुझे लगता है कि यह के कार्यान्वयन विस्तार क्रम में एक बग है, के बाद से सी # कल्पना एक नल-प्रकार को

अनबॉक्सिंग कहते nullable- के शून्य मान का उत्पादन टाइप करें कि स्रोत ऑपरेंड शून्य है, या ऑब्जेक्ट इंस्टेंस को अनबॉक्सिंग के लपेटने के परिणाम को अन्य प्रकार के नलिका-प्रकार के अंतर्निहित प्रकार पर टाइप करें।

यही है, अगर StringComparison को unboxing काम करता है, तो <StringComparison> नल को unboxing भी काम करना चाहिए। यह थोड़ा अस्पष्ट है कि दोनों को काम करना चाहिए या दोनों को असफल होना चाहिए। कल्पना का कहना है कि

किसी दिए गए गैर-व्यर्थ-मूल्य-प्रकार के लिए एक unboxing रूपांतरण के लिए रन-टाइम में सफल होने के लिए, स्रोत संकार्य के मूल्य कि गैर-व्यर्थ की एक बॉक्स्ड मूल्य के लिए एक संदर्भ होना चाहिए -मान प्रकार।

आपको यह तय करना होगा कि बॉक्सिंग इंट को स्ट्रिंग कॉम्परिसन प्रकार का बॉक्स बॉक्स माना जाता है क्योंकि अंतर्निहित प्रकार स्ट्रिंग कॉम्परिसन int है। यह कहने के लिए चला जाता है कि बॉक्स में "असंगत वस्तु" होने पर एक अवैध कैस्ट अपवाद फेंक दिया जाता है।एक int निश्चित रूप से स्ट्रिंग कॉम्परिसन के साथ "संगत" है, क्योंकि आप अपने स्ट्रिंग कॉम्पैरिसन चर में ढेर से चार बाइट्स को सुरक्षित रूप से कॉपी कर सकते हैं।

+1

पुन: रनटाइम में बग: मैं नहीं कहूंगा कि यह रनटाइम में * * बग * है; बल्कि, रनटाइम कुछ मामलों में सी # spec की तुलना में अधिक उदार है। यह केवल अत्यधिक लागत पर है कि हम सी # कार्यान्वयन के व्यवहार को वास्तविक लाभ के लिए, कल्पना के सख्त कार्यान्वयन के लिए प्रतिबंधित कर सकते हैं। –

+1

पुन: "संगत" प्रकार: हाँ, यह spec में हाथ का एक हाथ है। सीएलआर नियम थोड़ा असंगत हैं। उदाहरण के लिए, यह दिलचस्प है कि भले ही int और uint को एआरएल कॉन्वर्सिस के प्रयोजनों के लिए सीएलआर में संगत प्रकार माना जाता है, फिर भी उन्हें अनबॉक्सिंग के प्रयोजनों के लिए सीएलआर में संगत प्रकार नहीं माना जाता है, भले ही int और enum हैं। –

+0

उचित बिंदु, "बग" थोड़ा कठोर है। मैं पहली उद्धृत बिट को "int के लिए अनबॉक्सिंग" के रूप में पढ़ रहा था, जब इंट वर्किंग के लिए अनबॉक्सिंग करते समय काम करना चाहिए ", जब यह वास्तव में" int को अनबॉक्सिंग कर रहा है? तो काम करना चाहिए * int * करना * काम करना चाहिए "। मेरा मुद्दा वास्तव में था कि spec माइकल के अंतर्ज्ञान से सहमत है और अलग-अलग परिणाम एक जानबूझकर डिजाइन निर्णय के बजाए रनटाइम की उदारता का "दुर्घटना" है जो निरर्थक enums को अनबॉक्सिंग अमान्य होना चाहिए। – stevemegson

-1

1) हां, अंतर्निहित प्रकार का enum int है और यही कारण है कि यह इस तरह से काम करता है। और भी अधिक। आप निम्न कार्य कर सकते हैं:

enum MyEnum 
{ 
    One = 1, 
    Two = 2, 
} 

int i = 3; 
MyEnum myEnum = (MyEnum)i; // This works without exceptions. 

2) क्योंकि StringComparison? वास्तव में Nullable<StringComparison> जो विभिन्न प्रकार है। और as ऑपरेटर केवल जांचता है कि क्या ऑब्जेक्ट उसी प्रकार का है जैसा ऑपरेटर के रूप में निर्दिष्ट है।

+0

हां, लेकिन आप 'long @long = (long) intvar भी कर सकते हैं; इसका मतलब यह नहीं है कि आप लंबे समय तक एक int को अनबॉक्स कर सकते हैं। –

1

जब आप वस्तु के लिए enum या पूर्णांक डालें, तब भी यह प्रकार की जानकारी रखता है। तो box is StringComparisonfalse वापस आ जाएगा। लेकिन किसी भी enum या int को किसी भी enum के लिए डालने की अनुमति है, तो स्पष्ट कास्ट (StringComparison)box काम करता है। यह enums के लिए एक विशेष मामला है। दूसरी तरफ Nullable<T>, केवल एक सामान्य वर्ग है, टी को किसी भी विशिष्ट तरीके से संभाला नहीं जाता है जब आप कास्ट या चेक टाइप करते हैं। यही कारण है कि यह कोड अपवाद फेंक देगा।

 StringComparison? nullableEnum = (StringComparison?)nullableInt; 
संबंधित मुद्दे