2012-01-10 15 views
6

क्या कोई तकनीकी कारण है कि डीबीएनयूएल से विभिन्न शून्य और/या एसक्यूएल प्रकारों में कोई अंतर्निहित रूपांतरण क्यों नहीं है? मैं समझता हूं कि रूपांतरण वर्तमान में क्यों नहीं होते हैं, लेकिन समझ में नहीं आता कि उस समय एक अंतर्निहित रूपांतरण क्यों नहीं बनाया गया था या ढांचे के बाद के संस्करणों में जोड़ा गया था।क्या डीबीएनयूएल से नामुमकिन प्रकारों में कोई अंतर्निहित रूपांतरण नहीं होने का कोई तकनीकी कारण है?

बस स्पष्ट होने के लिए, मैं तकनीकी कारणों की तलाश में हूं, क्योंकि "ऐसा नहीं है कि उन्होंने ऐसा किया" या "मुझे यह पसंद है"।

+0

@DanielPryden: ठीक है, तो आप इस पर अगर लक्ष्य एक मूल्य या संदर्भ प्रकार था आधार पर एक अलग मूल्य में unboxing होगी? क्या यही मतलब है तुम्हारा? – jmoreno

+0

@ डैनियलप्रिडेन: सवाल फिर से खोला गया है, उम्मीद है कि इस बार यह आपके उत्तर देने के लिए पर्याप्त समय तक खुला रहेगा। – jmoreno

+0

ठीक है, मैंने इस जवाब को फिर से लिखा है, इस बार spec के संदर्भ के साथ। यह सोचता है कि यह वास्तव में उससे भी बदतर है: इस बिंदु पर, मुझे बहुत आश्वस्त है कि यह सिर्फ एक बुरा विचार नहीं है, यह पूरी तरह असंभव है। उम्मीद है कि मेरा जवाब इंतजार के लायक था! –

उत्तर

3

ठीक है, मैं 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.ValueNullable<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); 
+1

हाँ, यह के लिए इंतजार लायक था की जांच करने के IsNull संपत्ति का उपयोग करें। एक छोटा सा चेतावनी, सी # अशक्त कोलेसिंग ऑपरेटर वास्तव में रूपांतरण काफी सरल (एक अलग तंत्र है, जिसके कारण मैं ढांचे के बारे में पूछ रहा था के माध्यम से) बना देता है। int? int = x int int के रूप में? ?? शून्य; यह सी # कंपाइलर के लिए विशिष्ट है और ?? ऑपरेटर, और जबकि कोई भी भाषा निश्चित रूप से समकक्ष जोड़ सकती है, यह सीएलआर में निहित नहीं है (जो मुझे रूचि है)। – jmoreno

+0

@jmoreno: हम्म ... कि 'as' और के साथ एक चतुर चाल है' '?? ऑपरेटरों, मुझे लगता है कि एक सोचा नहीं था। यह शायद 'गतिशील' की तुलना में अधिक प्रदर्शनकारी होगा, हालांकि मुझे अभी भी नहीं लगता कि आप इसे * निहित * रूपांतरण ऑपरेटर के रूप में कर सकते हैं, क्योंकि आपको उचित मूल्य प्रकार जानने की आवश्यकता होगी। आप शायद इसे * स्पष्ट * रूपांतरण ऑपरेटर के साथ कर सकते हैं, हालांकि आप इसके बजाय एक विस्तार विधि का प्रयास करना चाहेंगे, जिसके साथ काम करना आसान हो सकता है। –

+0

सही, मुझे नहीं लगता कि आप इसे एक निहित ऑपरेटर के साथ भी कर सकते हैं। सी # में आप एक विस्तार विधि लिख सकता है, तो आप ऐसा नहीं कर सकते कि VB में के रूप में यह तुम क्योंकि लेट बाइंडिंग के साथ संभव संघर्ष की वस्तु के लिए ऐसा करने नहीं देता। मेरे पास वीबी के लिए एक सामान्य उपयोगिता कार्य है, जो काम करता है। – jmoreno

7

सबसे सरल व्याख्या Microsoft's documentation से आता है:

CLR नल प्रकार डेटाबेस nulls के भंडारण के लिए इरादा नहीं है, क्योंकि एक ANSI SQL अशक्त दृश्य में एक अशक्त संदर्भ के रूप में एक ही तरह से (या कुछ भी नहीं है व्यवहार न करे बेसिक)।

+5

दूसरे शब्दों में, हमने जानबूझकर ऐसा नहीं किया क्योंकि हम चाहते हैं कि आप जो भी कर रहे हैं उसके बारे में पूरी तरह से अवगत रहें। – NotMe

+0

@competent_tech: वहाँ से अगले ही वाक्य है "। डेटाबेस ANSI SQL शून्य मान के साथ काम करने के लिए, System.Data.SqlTypes nulls बल्कि Nullable से उपयोग करें", लेकिन ... "प्रकार के मान 'System.DBNull' नहीं बदला जा सकता करने के लिए 'System.Data.SqlTypes.SqlInt32' " – jmoreno

+0

@jmoreno: मुझे लगता है कि यह शून्य मान बताए तहत थोड़ा और आगे नीचे संबोधित किया जाता है:' System.Data.SqlTypes में Nulls विशेष प्रकार के होते हैं और एक एकल मान के अनुसार नहीं दर्शाया जा सकता , जैसे डीबीएनयूएल। nulls.' –

संबंधित मुद्दे

 संबंधित मुद्दे