2009-07-23 8 views
40

मेरे पास सी # 2.0 स्रोत कोड का यह निकास है:सी #?: सशर्त ऑपरेटर

object valueFromDatabase; 
decimal result; 
valueFromDatabase = DBNull.Value; 

result = (decimal)(valueFromDatabase != DBNull.Value ? valueFromDatabase : 0); 
result = (valueFromDatabase != DBNull.Value ? (decimal)valueFromDatabase : (decimal)0); 

पहला परिणाम मूल्यांकन InvalidCastException फेंकता है जबकि दूसरा वाला नहीं है। इन दोनों के बीच क्या अंतर है?

+0

मैं यह स्पष्ट करना चाहता हूं कि पहले लोगों में शून्य का मूल्यांकन होता है, न कि DBNull.value पर। दशमलव को 0 कास्टिंग क्यों अपवाद फेंकता है? – Ioannis

उत्तर

100

अद्यतन का मूल्यांकन करना चाहिए है: यह सवाल the subject of my blog on May 27th 2010 था। महान सवाल के लिए धन्यवाद!

यहां बहुत सारे भ्रमित उत्तर हैं। मुझे अपने प्रश्न का सही जवाब देने की कोशिश करें। आइए इसे सरल बनाएं:

object value = whatever; 
bool condition = something; 
decimal result = (decimal)(condition ? value : 0); 

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

decimal result = (decimal)(condition ? (object)value : (object)0); 

इसलिए शून्य लौटा हुआ एक बॉक्सिंग int है।

फिर आप दशमलव को int को अनबॉक्स करते हैं। दशमलव पर बॉक्स किए गए int को अनबॉक्स करना अवैध है। कारण, उस विषय पर अपने ब्लॉग लेख देखें:

Representation and Identity

असल में, आपकी समस्या यह है कि आप कार्य कर रहे हैं जैसे कि दशमलव के कलाकारों वितरित किए गए, इस तरह है:

decimal result = condition ? (decimal)value : (decimal)0; 

लेकिन जैसा कि हमने देखा है, यह

decimal result = (decimal)(condition ? value : 0); 

का अर्थ है। इसका मतलब है "ऑब्जेक्ट्स में दोनों विकल्प बनाएं और फिर परिणामस्वरूप ऑब्जेक्ट को अनबॉक्स करें"।

result = (decimal)(valueFromDatabase != DBNull.Value ? (decimal)valueFromDatabase : (decimal)0); 

कम से कम, एक ऐसी ही स्थिति मेरे लिए एक पैरामीटर में कास्टिंग: यदि आप संयुक्त दोनों

+7

+1 अच्छा स्पष्टीकरण है। –

+0

मुझे समझ में नहीं आता क्यों संकलक टाइप रूपांतरणों को सम्मिलित कर रहा है जहां संकलन त्रुटि अधिक उपयुक्त प्रतीत होती है। – raj

+2

@raj: संकलन त्रुटि कब देना है यह निर्धारित करने के लिए आप किस नियम को लागू करना चाहते हैं? –

12

अंतर यह है कि संकलक Object और Int32 के बीच एक अच्छा मिलान निर्धारित डेटा प्रकार निर्धारित नहीं कर सकता है।

आप स्पष्ट रूप से इतना है कि यह संकलित दूसरे और तीसरे संकार्य में एक ही डेटा प्रकार प्राप्त करने के लिए object को int मूल्य डाल सकता है, लेकिन इसका मतलब couse की है कि आप मुक्केबाजी कर रहे हैं और unboxing मूल्य:

result = (decimal)(valueFromDatabase != DBNull.value ? valueFromDatabase : (object)0); 

वह संकलित करेगा, लेकिन नहीं चलाएगा। आप दशमलव मान के रूप Unbox करने के लिए दशमलव मान बॉक्स करने के लिए है:

result = (decimal)(valueFromDatabase != DBNull.value ? valueFromDatabase : (object)0M); 
+0

सी # विशिष्टता: "एक मुक्केबाजी रूपांतरण एक मूल्य-प्रकार को संदर्भ रूप से संदर्भ प्रकार में परिवर्तित करने की अनुमति देता है। एक मुक्केबाजी रूपांतरण किसी भी गैर-शून्य-मूल्य-प्रकार से ऑब्जेक्ट में, सिस्टम.वेल्यू टाइप और किसी भी इंटरफ़ेस-प्रकार के लिए मौजूद है गैर-शून्य-मूल्य-प्रकार द्वारा कार्यान्वित किया गया है। इसके अलावा एक enum-type को सिस्टम.इनम में परिवर्तित किया जा सकता है। " तो Int32 और ऑब्जेक्ट के बीच निहित मुक्केबाजी रूपांतरण है। यदि कंपाइलर प्रकार निर्धारित नहीं कर सका तो यह संकलन समय पर विफल हो जाएगा और रनटाइम पर नहीं। कृपया मेरा उत्तर देखें ... –

3

x: y हिस्सा एक सामान्य प्रकार की जरूरत है, डेटाबेस के मूल्य की संभावना नाव किसी तरह का है और 0 किसी पूर्णांक है। यह कास्ट को दशमलव से पहले होता है। "0.0" या "0 डी" आज़माएं।

+0

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

+1

जैसा कि अन्य ने कहा है, यह 0 एम – KClough

+0

प्रकार का दशमलव शून्य दशमलव: 0 मीटर है। – Richard

5

ऑपरेटर का प्रकार ऑब्जेक्ट होगा और यदि परिणाम 0 होना चाहिए तो यह निश्चित रूप से बॉक्स किया जाएगा। लेकिन 0 शाब्दिक डिफ़ॉल्ट रूप से int प्रकार है इसलिए आप बॉक्स int। लेकिन दशमलव पर स्पष्ट कास्ट के साथ आप इसे अनबॉक्स करने का प्रयास करते हैं, जिसकी अनुमति नहीं है (बॉक्स किए गए प्रकार को उस व्यक्ति के साथ बहुत अधिक होना चाहिए जिसे आपने वापस डाला था)। यही कारण है कि आप अपवाद प्राप्त कर सकते हैं। ?

के दूसरे और तीसरे ऑपरेंड: ऑपरेटर नियंत्रण सशर्त अभिव्यक्ति के प्रकार

यहाँ सी # विशिष्टता से एक अंश है। एक्स और वाई को दूसरे और तीसरे ऑपरेंड के प्रकार होने दें। फिर,

  • यदि एक्स और वाई समान प्रकार हैं, तो यह सशर्त अभिव्यक्ति का प्रकार है।
  • अन्यथा, यदि एक अंतर्निहित रूपांतरण (§6.1) एक्स से वाई तक मौजूद है, लेकिन वाई से एक्स तक नहीं है, तो वाई सशर्त अभिव्यक्ति का प्रकार है।
  • अन्यथा, यदि कोई अंतर्निहित रूपांतरण (§6.1) वाई से एक्स तक मौजूद है, लेकिन एक्स से वाई तक नहीं है, तो एक्स सशर्त अभिव्यक्ति का प्रकार है।
  • अन्यथा, कोई अभिव्यक्ति प्रकार निर्धारित नहीं किया जा सकता है, और संकलन-समय त्रुटि उत्पन्न होती है।
2

जब तक कि मैं गलत नहीं हूं (जो बहुत संभव है) वास्तव में 0 है जो अपवाद पैदा कर रहा है, और यह एक शाब्दिक प्रकार के मानते हुए .NET (पागलपन) तक है, इसलिए आपको 0m निर्दिष्ट करने की आवश्यकता है बस 0.

अधिक जानकारी के लिए MSDN देखें।

0

कंपाइलर के निर्णय के लिए दो अलग-अलग प्रकार हैं (संकलन समय पर) जिसे दशमलव पर डालना है। यह ऐसा नहीं कर सकता है।

4

आपका लाइन किया जाना चाहिए:

result = valueFromDatabase != DBNull.value ? (decimal)valueFromDatabase : 0m; 

0m शून्य

के लिए दशमलव लगातार एक सशर्त ऑपरेटर के दोनों भाग एक ही डेटा प्रकार को

+0

यह संभवतः दूसरी पंक्ति के समान कोड में संकलित होगा। – Guffa

+0

हो सकता है, लेकिन यह इंगित करने योग्य है कि शून्य के लिए दशमलव स्थिरांक –

-1

आपका जवाब काम करेगा।

+0

यह कोई समझ नहीं आता है: चूंकि आपने दोनों शाखाएं डाली हैं, प्रारंभिक कास्ट बेकार है। –