अशक्त प्रकार का मुद्दा ?: सशर्त संचालक


154

क्या कोई समझा सकता है कि यह C # .NET 2.0 में क्यों काम करता है:

    Nullable<DateTime> foo;
    if (true)
        foo = null;
    else
        foo = new DateTime(0);

... लेकिन यह नहीं है:

    Nullable<DateTime> foo;
    foo = true ? null : new DateTime(0);

बाद का रूप मुझे एक जटिल त्रुटि देता है "प्रकार की सशर्त अभिव्यक्ति निर्धारित नहीं की जा सकती है क्योंकि '<null>' और 'System.DateTime' के बीच कोई अंतर्निहित रूपांतरण नहीं है।"

ऐसा नहीं है कि मैं पूर्व का उपयोग नहीं कर सकता, लेकिन दूसरी शैली मेरे कोड के बाकी हिस्सों के साथ अधिक सुसंगत है।


12
आप डेटटाइम का उपयोग करके अपने आप को बहुत अधिक टाइपिंग से बचा सकते हैं? Nullable के बजाय <DateTime>।
स्टीवर्ट जॉनसन

जवाबों:


325

यह सवाल पहले से कई बार पूछा गया है। संकलक आपको बता रहा है कि यह नहीं जानता कि कैसे nullएक में परिवर्तित होता है DateTime

समाधान सरल है:

DateTime? foo;
foo = true ? (DateTime?)null : new DateTime(0);

ध्यान दें कि Nullable<DateTime>लिखा जा सकता है DateTime?जो आपको टाइपिंग का एक गुच्छा बचाएगा।


अच्छी तरह से काम करता है, लेकिन अब आप foo को चेक नहीं कर सकते हैं - इसका हमेशा एक मूल्य होगा। हालांकि इसके आसपास कोई रास्ता नहीं है - जैसा कि मोजोफिल्टर कहते हैं, "यह इसलिए है क्योंकि एक टर्नरी ऑपरेटर में, दो मान एक ही प्रकार के होने चाहिए।"
दिलबर्टडैव

@DilbertDave MojoFilter के पोस्ट की जानकारी गलत है।
मिशाक्स

4
मैं जोड़ूंगा कि कंपाइलर परिणामी प्रकार के टर्नरी ऑपरेशन का अनुमान लगाने की कोशिश करता है न कि उस चर को देखकर जिसे वह सौंपा गया है, लेकिन इसके बजाय ऑपरेंड को देखकर। यह सामान्य पूर्वज प्रकार को खोजने के बजाय पाता है <null>और DateTimeएक दूसरे के बीच रूपांतरण खोजने की कोशिश करता है। (अतिरिक्त बिट: C # एक <null>प्रकार को पहचानता है , अर्थात हर nullअभिव्यक्ति का प्रकार ।)
इलिडानस

यदि यह पहले से ही पूछा गया है कि डुप्लिकेट प्रश्न ध्वज कहाँ है?
स्ट्रामांडेलिक

@starmandelmill वे सभी संभावित बिंदु यहां (कम से कम यह है कि मैं यहां कैसे आया)
स्कॉट चैंबरलेन

19

FYI (ऑफटॉपिक, लेकिन निफ्टी और अशक्त प्रकार से संबंधित) हमारे पास एक उपयोगी ऑपरेटर है जो केवल अशक्त प्रकारों के लिए है, जिसे अशक्त कर्लिंग ऑपरेटर कहा जाता है

??

इस तरह इस्तेमाल किया:

// Left hand is the nullable type, righthand is default if the type is null.
Nullable<DateTime> foo;
DateTime value = foo ?? new DateTime(0);

9
यह उनके सवाल का जवाब कैसे देता है ??
स्टीवर्ट जॉनसन

3
निक कुछ स्थिति सच होने पर फू को अशक्त करने की कोशिश कर रहा है। अशक्त coalesce DateTime (0) को महत्व देगा यदि फू शून्य है। दो पूरी तरह से असंबंधित हैं।
जेरोमे इरविन

4
इसलिए FYI करें, ऑफटॉपिक लेकिन जानने के लिए एक अच्छी बात है।
फ्लायस्वत

आह अच्छा। यह जानना बहुत उपयोगी है।
जेरोमे इरविन

8

ऐसा इसलिए है क्योंकि एक टर्नरी ऑपरेटर में, दोनों मानों को एक ही प्रकार से हल होना चाहिए।


10
नहीं, उन्हें एक ही प्रकार का नहीं होना चाहिए। या तो दूसरे ऑपरेंड को तीसरे ऑपरेंड के प्रकार या आसपास के अन्य तरीके से स्पष्ट रूप से परिवर्तनीय होना चाहिए।
21

3

मुझे पता है कि यह प्रश्न 2008 में पूछा गया था और यह अब 5 साल बाद है लेकिन उत्तर के रूप में चिह्नित उत्तर मुझे संतुष्ट नहीं करता है। वास्तविक उत्तर यह है कि डेटटाइम एक संरचना है, और एक संरचना के रूप में यह अशक्त के साथ संगत नहीं है। आपके पास इसे हल करने के दो तरीके हैं:

पहले डेटटाइम के साथ अशक्त बनाने के लिए है (उदाहरण के लिए, डेटटाइम के लिए कास्ट नल। जैसा कि 70 अपवित्र के साथ सज्जन का सुझाव है, या ऑब्जेक्ट या वैल्यू टाइप करने के लिए अशक्त है)।

दूसरा है डेटटाइम को नल के साथ संगत करना (उदाहरण के लिए, डेटटाइम को डेटटाइम के लिए?)।


3

स्वीकृत के समान एक अन्य समाधान C # के defaultकीवर्ड का उपयोग करना है । जेनरिक का उपयोग करते हुए परिभाषित किया गया है, यह वास्तव में किसी भी प्रकार पर लागू होता है।

ओपी के प्रश्न पर लागू उदाहरण का उपयोग:

Nullable<DateTime> foo;
foo = true ? default(DateTime) : new DateTime(0);

वर्तमान स्वीकृत उत्तर के साथ उदाहरण का उपयोग:

DateTime? foo;
foo = true ? default(DateTime) : new DateTime(0);

इसके अलावा, उपयोग करके default, आपको वैरिएबल को निर्दिष्ट करने की आवश्यकता नहीं है nullable, ताकि इसे nullमान दिया जा सके। कंपाइलर विशिष्ट चर-प्रकार के डिफ़ॉल्ट मान को ऑटो-असाइन करेगा और कोई त्रुटि नहीं होगी। उदाहरण:

DateTime foo;
foo = true ? default(DateTime) : new DateTime(0);

13
सच नहीं है, default(DateTime)अशक्त नहीं है, यह " 1.1.0001 0:00:00" है, उसी के रूप में new DateTime(0)
इलिडान्स

@ IllidanS4, मैंने यह नहीं कहा कि यह बराबर है null, केवल default()इसका उपयोग करके आप इसे एक nullableमूल्य पर निर्दिष्ट कर सकते हैं (जैसा कि MSDN स्टेट्स)। उदाहरण मैं दिखाने के बहुमुखी प्रतिभा है कि यह साथ इस्तेमाल किया जा सकता का प्रदर्शन Nullable<DateTime>, DateTime?और बस DateTime। यदि आप इसे गलत मानते हैं, तो क्या आप एक PoC प्रदान कर सकते हैं जहाँ ये विफल हो जाते हैं?
newfendoy

3
ठीक है, प्रश्नकर्ता nullचर में संग्रहीत करना चाहता था , नहीं default(DateTime), इसलिए यह सबसे अच्छा भ्रामक है। यह "बहुमुखी" के रूप में आप मतलब, एक पूरे के रूप अभिव्यक्ति अभी भी एक ही प्रकार के बाद से नहीं है - DateTime, और आप बदल सकते हैं default(DateTime)के साथ new DateTime()और यह एक ही काम करेंगे। हो सकता default(DateTime?)है कि आपका मतलब क्या था, क्योंकि यह वास्तव में बराबर है null
IllidanS4 चाहता है कि मोनिका 20
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.