ठीक है, मैं SqlTypes
मामले के बारे में पता नहीं है, लेकिन वहाँ निश्चित रूप से कुछ तकनीकी वजहों DBNull.Value
और HasValue = false
साथ Nullable<T>
के मूल्यों कार्य नहीं करेगा के बीच एक अंतर्निहित रूपांतरण जोड़ने कर रहे हैं।
याद रखें, DBNull
एक संदर्भ प्रकार है, और तथ्य यह है कि Nullable<T>
कृत्यों एक संदर्भ प्रकार की तरह के बावजूद - का बहाना बनाकर null
मूल्य पर लेने के लिए सक्षम होने के लिए - यह वास्तव में एक मान प्रकार है, मूल्य अर्थ विज्ञान के साथ।
विशेष रूप से, एक अजीब किनारा मामला है जब Nullable<T>
प्रकार के मान बॉक्स किए गए हैं। के बॉक्स किए गए संस्करण में Nullable<T>
के बॉक्स किए गए संस्करण के लिए Nullable<T>
के बॉक्स मानों के लिए रनटाइम में व्यवहार को विशेषीकृत किया गया है।
the MSDN documentation के रूप में यह बताते हैं:
जब एक नल प्रकार बॉक्सिंग जाता है, आम भाषा क्रम स्वचालित रूप से बॉक्स Nullable (टी के) के अंतर्निहित कीमत वस्तु, नहीं Nullable (टी का) वस्तु ही। यही है, अगर HasValue संपत्ति सत्य है, तो मूल्य संपत्ति की सामग्री को बॉक्स किया गया है। जब एक नालीबल प्रकार का अंतर्निहित मान अनबॉक्स किया जाता है, तो सामान्य भाषा रनटाइम अंतर्निहित मूल्य के लिए प्रारंभ की गई एक नई न्यूलबल (टी) संरचना बनाता है।
यदि एक नामुमकिन प्रकार की HasValue संपत्ति गलत है, तो मुक्केबाजी ऑपरेशन का नतीजा कुछ भी नहीं है। नतीजतन, यदि एक बॉक्सिंग नालीबल प्रकार किसी विधि को पास किया जाता है जो किसी ऑब्जेक्ट तर्क की अपेक्षा करता है, तो उस विधि को संभालने के लिए उस विधि को तैयार किया जाना चाहिए जहां तर्क कुछ भी नहीं है। जब कुछ भी एक शून्य प्रकार में अनबॉक्स नहीं किया जाता है, तो सामान्य भाषा रनटाइम एक नई नलबल (टी) संरचना बनाता है और इसकी हैस्वेलू प्रॉपर्टी को गलत में प्रारंभ करता है।
अब हम एक मुश्किल समस्या में मिलती है: सी # भाषा कल्पना (§ 4.3.2) का कहना है हम कन्वर्ट करने के लिए एक unboxing रूपांतरण उपयोग नहीं कर सकते DBNull.Value
Nullable<T>
में:
को एक unboxing रूपांतरण के लिए किसी दिए गए नल प्रकार रन-टाइम में सफल होने के लिए, स्रोत संकार्य का मान न तो नल या नल प्रकार के अंतर्निहित गैर-व्यर्थ-मूल्य-प्रकार की एक बॉक्स्ड मूल्य के लिए एक संदर्भ होना चाहिए ।यदि स्रोत ऑपरेंड एक असंगत वस्तु का संदर्भ है, तो System.InvalidCastException
फेंक दिया गया है।
और हम उपयोगकर्ता-निर्धारित रूपांतरण का उपयोग नहीं कर सकते object
से Nullable<T>
में बदलने के लिए, या तो, § 10.10.3 के अनुसार:
यह संभव नहीं है सीधे फिर से परिभाषित करने के लिए एक पूर्व निर्धारित रूपांतरण। इस प्रकार, रूपांतरण ऑपरेटरों को object
से कनवर्ट करने की अनुमति नहीं है क्योंकि object
और अन्य सभी प्रकारों के बीच निहित और स्पष्ट रूपांतरण पहले से मौजूद हैं।
ठीक है, आप या मैं यह नहीं कर सका, लेकिन माइक्रोसॉफ्ट सिर्फ कल्पना में संशोधन कर सकता है, और यह कानूनी है, है ना बनाते हैं? मुझे ऐसा नहीं लगता।
क्यों? खैर, इच्छित उपयोग केस की कल्पना करें: आपके पास कुछ विधि है जो object
लौटने के लिए निर्दिष्ट है। अभ्यास में, यह या तो DBNull.Value
या int
देता है। लेकिन संकलक को यह कैसे पता चलेगा? यह सब जानता है कि विधि object
लौटने के लिए निर्दिष्ट है। और रूपांतरण ऑपरेटर लागू किया जाना चाहिए संकलन समय पर चुना जाना चाहिए।
ठीक है, तो मान लीजिए कि कुछ जादुई ऑपरेटर हैं जो object
से Nullable<T>
में परिवर्तित हो सकते हैं, और संकलक के पास लागू होने पर जानने का कोई तरीका है। (हम यह नहीं चाहते हैं कि प्रत्येक विधि object
लौटने के लिए निर्दिष्ट विधि के लिए उपयोग किया जाए - विधि वास्तव में string
लौटाता है तो क्या करना चाहिए?) लेकिन हमें अभी भी कोई समस्या है: रूपांतरण अस्पष्ट हो सकता है! यदि विधि या तो long
, या DBNull.Value
लौटाती है, और हम int? v = Method();
करते हैं, तो विधि को बॉक्सिंग long
पर बॉक्स करने पर हमें क्या करना चाहिए?
असल में, इस काम को इरादे से बनाने के लिए, आपको रनटाइम पर टाइप निर्धारित करने और रनटाइम प्रकार के आधार पर कनवर्ट करने के लिए dynamic
के बराबर उपयोग करना होगा। लेकिन फिर हमने एक और नियम तोड़ दिया है: चूंकि वास्तविक रूपांतरण केवल रनटाइम पर ही चुना जाएगा, इस बात की कोई गारंटी नहीं है कि यह वास्तव में सफल होगा। लेकिन निहित रूपांतरण अपवाद फेंकने के लिए नहीं माना जाता है।
तो इस बिंदु पर, यह न केवल भाषा के निर्दिष्ट व्यवहार में बदलाव है, संभावित रूप से महत्वपूर्ण प्रदर्शन हिट है, और इसके शीर्ष पर यह एक अप्रत्याशित अपवाद फेंक सकता है! ऐसा लगता है कि इसे लागू करने के लिए एक बहुत अच्छा कारण नहीं है। लेकिन अगर आपको एक और कारण की आवश्यकता है, तो याद रखें कि प्रत्येक सुविधा minus 100 points से शुरू होती है।
संक्षेप में: आप जो वास्तव में यहां चाहते हैं वैसे भी एक निहित रूपांतरण के साथ नहीं किया जा सकता है। यदि आप dynamic
का व्यवहार चाहते हैं, तो बस dynamic
का उपयोग करें! यह तुम क्या चाहते है, और पहले से ही सी # 4.0 में कार्यान्वित किया जाता है:
object x = 23;
object y = null;
dynamic dx = x;
dynamic dy = y;
int? nx = (int?) dx;
int? ny = (int?) dy;
Console.WriteLine("nx.HasValue = {0}; nx.Value = {1}; ny.HasValue = {2};",
nx.HasValue, nx.Value, ny.HasValue);
@DanielPryden: ठीक है, तो आप इस पर अगर लक्ष्य एक मूल्य या संदर्भ प्रकार था आधार पर एक अलग मूल्य में unboxing होगी? क्या यही मतलब है तुम्हारा? – jmoreno
@ डैनियलप्रिडेन: सवाल फिर से खोला गया है, उम्मीद है कि इस बार यह आपके उत्तर देने के लिए पर्याप्त समय तक खुला रहेगा। – jmoreno
ठीक है, मैंने इस जवाब को फिर से लिखा है, इस बार spec के संदर्भ के साथ। यह सोचता है कि यह वास्तव में उससे भी बदतर है: इस बिंदु पर, मुझे बहुत आश्वस्त है कि यह सिर्फ एक बुरा विचार नहीं है, यह पूरी तरह असंभव है। उम्मीद है कि मेरा जवाब इंतजार के लायक था! –