2011-12-20 9 views
7

मैं क्यों निम्नलिखित कोड काम करता है (वी.एस. डिबगर के अंतर्गत चलाने) के रूप में उत्सुक हूँ:एक इंट क्यों कर सकता है? शून्य के लिए सेट उदाहरण गुण हैं?

int? x = null; 
null 
x.HasValue 
false 

तो x वास्तव में रिक्त है, क्या उदाहरण को देखें HasValue करता है? HasValue एक विस्तार विधि के रूप में लागू किया गया है, या संकलक विशेष मामला यह जादुई रूप से काम करने के लिए करता है?

+1

शून्य प्रकार के साथ एक बहुत ही भयानक विशेष मामला गोचाचा है। रनटाइम स्वचालित रूप से मुक्केबाजी करते समय उनके आंतरिक मूल्य को कम कर देगा। इसका मतलब है कि "((ऑब्जेक्ट) x) .सवैल्यू" एक NullReferenceException फेंक देगा। यह खराब है। –

+0

@ केनेट बेलेन्की वास्तव में '((ऑब्जेक्ट) x) .सवैल्यू संकलित नहीं होगा, क्योंकि ऑब्जेक्ट पर कोई HasValue प्रॉपर्टी नहीं है। मुझे लगता है कि आप यह कहना चाहते थे कि '((ऑब्जेक्ट) x)। ToString()' (या '.GetHashCode()' या 'Equals (कुछ) ') फेंक देगा। – phoog

+0

@phoog, ओह, मैं अपने विवरण में थोड़ा जल्दी था। आप सही हैं, मेरा विवरण वाक्य रचनात्मक रूप से अमान्य है। बिंदु यह है कि, हालांकि, जिस क्षण आपने किसी ऑब्जेक्ट को एक नालीबल डाला था, यह अब एक नामुमकिन नहीं है। नेट फ्रेमवर्क में कोई अन्य प्रकार उस संपत्ति में नहीं है। –

उत्तर

9

क्योंकि x एक संदर्भ प्रकार नहीं है। ?Nullable<T> के लिए सिंटैक्टिक चीनी है, जो struct (मान प्रकार) है।

+0

यह सबसे अधिक समझ में आता है। तुलना और असाइनमेंट ऑपरेटरों को तब भी ओवरलोड किया जाएगा। हालांकि, जो चीज मुझे भ्रमित करती है वह यह है कि यदि मैं वॉच विंडो के नीचे 'x' देखता हूं, तो यह' शून्य 'दिखाता है (यदि यह वास्तव में एक मान प्रकार है तो असंभव होना चाहिए)। वीएस डीबगर विशेष मामला यह है? –

+0

@ माइक: ठीक है, वीएस डीबगर एक अजीब जानवर है। लेकिन मुझे लगता है कि इस मामले में यह केवल Nullable की 'ToString()' विधि का उपयोग कर रहा है। – Cameron

+0

@ कैमरून, टूस्ट्रिंग() एक नालीबल के लिए एक emtpy स्ट्रिंग को वापस करने के लिए प्रलेखित किया गया है यदि मान शून्य के बराबर है। अगर मुझे निकल पर शर्त लगानी पड़ी, तो मैं कहूंगा कि डीबगर यह मुक्केबाजी कर रहा है, जो एक शून्य उत्पन्न करेगा। –

1

जब int? x = null तो x का उपयोग कर Nullable<int> का एक नया उदाहरण असाइन किया गया है और IST मूल्य null को तैयार है।

मुझे आंतरिक रूप से बिल्कुल पता नहीं है लेकिन मुझे लगता है कि असाइनमेंट ऑपरेटर स्वयं कुछ हद तक अधिभारित है।

5

int? वास्तव में एक संरचना Nullable<int> है। इसलिए, यह आपके x शून्य नहीं हो सकता है, क्योंकि यह हमेशा संरचना का उदाहरण होता है।

0

शून्य प्रकार (इस मामले में: शून्य करने योग्य int) में HasValue की एक संपत्ति है जो बूलियन है। यदि हैस्वाल्यू सही है, तो वैल्यू प्रॉपर्टी (टाइप टी, इस मामले में, एक इंट) का वैध मान होगा।

1

एक नल प्रकार वास्तव में null के बाद से यह अभी भी तथ्य यह है कि मूल्य प्रकार null नहीं कर सकते हैं चारों ओर नहीं मिलता नहीं है। इसके बजाय, Nullable<> संरचना का संदर्भ है (जो एक मान प्रकार भी है और null नहीं हो सकता है)।

अधिक जानकारी here

असल में, जब आप एक नामुमकिन प्रकार का उपयोग करते हैं तो आप हमेशा किसी चीज के उदाहरण का जिक्र कर रहे हैं। उस संदर्भ द्वारा लौटाई गई डिफ़ॉल्ट जानकारी संग्रहित मान (या null है यदि कोई संग्रहीत मूल्य नहीं है)।

1

Nullable वास्तव में एक संदर्भ प्रकार नहीं है, और इसकी आवृत्ति विधियां उन स्थानों में से एक हैं जहां यह दिखाई देती है। मूल रूप से, यह एक संरचना प्रकार है जिसमें एक बुलियन ध्वज होता है और जिस प्रकार का यह एक शून्य है। विशेष मामलों में विभिन्न ऑपरेटर [उठाने के लिए, या कुछ मामलों में उलझन (बूल?) शून्य झूठ बोलने के लिए] और शून्य शाब्दिक, और रनटाइम विशेष मामलों के मुक्केबाजी, लेकिन इसके अलावा यह सिर्फ एक संरचना है।

1

यह एक बिल्कुल नया प्रकार है। नल नहीं टी

क्या आप इस तरह एक सामान्य वर्ग के लिए कुछ है:

public struct Nullable<T> 
{ 
    public bool HasValue { get { return Value != null; } } 
    public T Value { get; set; } 
} 

मैं वहाँ यह करने के लिए और अधिक (विशेष रूप से गेटर और सेटर में है यकीन है, लेकिन यह एक में यह है । संक्षेप

+1

स्पष्ट ऑपरेटर भी हैं, लेकिन यह मूल रूप से यह है। जॉन स्कीट Depth_ में _C# में 'Nullable ' समझाते हुए एक बहुत अच्छा काम करता है। –

+0

असल में, यह एक सामान्य 'संरचना' है, न कि कक्षा। –

+0

- इस टिप्पणी को अनदेखा करें, डॉक ब्राउन द्वारा निंजा'd – DaveShaw

4

हाथ लहराते जवाब:। nullable structs जादू कर रहे हैं

लंबे समय तक जवाब:। अशक्त वास्तव में क्या मूल्य का प्रतिनिधित्व करती है नहीं है जब आप एक नल struct करने के लिए अशक्त असाइन करते हैं, क्या आप टी के पीछे हो देखेंगे वह दृश्य अलग है।

int? val = null; // what you wrote 
Nullable<Int32> val = new Nullable<Int32>(); // what is actually there 

इस मामले में, struct का एक उदाहरण बन जाता है है कि एक डिफ़ॉल्ट मान पर T Value सेट और bool HasValue संपत्ति गलत पर सेट।

केवल समय आप वास्तव में एक Nullable<T> से एक अशक्त संदर्भ प्राप्त करेंगे जब यह T या अशक्त करने के लिए सीधे एक Nullable<T> बक्से के रूप में, बॉक्सिंग है, अगर मान सेट है पर निर्भर करता है है।

2

null पर कई अर्थ हैं।

प्रोग्रामिंग भाषाओं में से एक जो पॉइंटर-आधारित तरीके में चर और स्मृति प्रस्तुत करता है (जिसमें सी # के संदर्भ शामिल हैं हालांकि यह कुछ विवरण छुपाता है) "यह कुछ भी इंगित नहीं करता है"।

दूसरा "इसका कोई सार्थक मूल्य नहीं है"।

संदर्भ प्रकारों के साथ, हम अक्सर बाद वाले का प्रतिनिधित्व करने के लिए पूर्व का उपयोग करते हैं। हम string label = null का उपयोग "कोई सार्थक लेबल नहीं कर सकते हैं। यह अभी भी भी स्मृति में कहां है और इसके बारे में क्या इंगित कर रहा है, इस मामले में क्या हो रहा है, इस मामले में क्या हो रहा है। फिर भी, यह बहुत उपयोगी है, हम कितना शर्मिंदा हैं सी # में int और DateTime के साथ ऐसा नहीं कर सकता है 1.1

क्या Nullable<T> प्रदान करता है यही कारण है, एक साधन कहते हैं "कोई सार्थक मूल्य", लेकिन यह नीचे के स्तर पर उसी तरह एक null स्ट्रिंग है में null नहीं है (जब तक बॉक्स किया गया)। इसे शून्य कहा गया है और शून्य के बराबर है इसलिए यह कुछ अन्य अर्थशास्त्र के अनुसार तार्किक रूप से शून्य और शून्य है, लेकिन यह संदर्भ और मूल्य प्रकारों के बीच कार्यान्वयन अंतर "कुछ भी इंगित नहीं करता है" में शून्य नहीं है।

यह संदर्भ-प्रकार नल के केवल "कुछ भी इंगित नहीं करता" पहलू है जो आपको उस पर उदाहरण विधियों को कॉल करने से रोकता है।

और वास्तव में, यहां तक ​​कि यह सख्ती से सच नहीं है। आईएल चलो आप एक संक्षिप्त संदर्भ पर उदाहरण विधियों को कॉल करते हैं और जब तक यह किसी भी क्षेत्र से बातचीत नहीं करता है, यह काम करेगा। अगर यह जरूरत है यह काम कर सकते हैं नहीं (प्रत्यक्ष या परोक्ष) उन क्षेत्रों के बाद से वे एक अशक्त refernce पर मौजूद नहीं हैं, लेकिन यह null.FineWithNull() कह सकते हैं कि अगर विधि के रूप में परिभाषित किया गया था: सी # के साथ यह निर्णय लिया गया

int FineWithNull() 
{ 
    //note that we don't actually do anything relating to the state of this object. 
    return 43; 
} 

इसे अस्वीकार करने के लिए, लेकिन यह सभी .NET के लिए नियम नहीं है (मुझे लगता है कि एफ # इसे अनुमति देता है, लेकिन मुझे यकीन नहीं है, मुझे पता है कि अप्रबंधित सी ++ ने इसे अनुमति दी है और यह कुछ दुर्लभ मामलों में उपयोगी था)।

+0

मेरा मानना ​​है कि सी # वास्तव में इस मामले में अनुमति देता है जहां विधि कक्षा का विस्तार तरीका है। निश्चित रूप से शून्य पर एक दिलचस्प सारांश, '+ 1'! –

+0

@ माइक क्रिस्टेनसेन आप उस पर सही हैं, हालांकि उस स्थिति में क्या हो रहा है कि सी # एक स्थैतिक विधि कॉल को पहला तर्क देने की इजाजत दे रहा है - क्योंकि कोई भी किसी भी भाषा में शून्य की अवधारणा के साथ अपेक्षा करता है - और फिर इसे अनुमति देता है उदाहरण विधियों के रूप में एक ही वाक्यविन्यास के साथ बुलाया जाना है। –

+0

@ माइक क्रिस्टेनसेन एक दिलचस्प विडंबना है कि सी # ने अधिकांश कॉल के लिए 'कॉलवर्ट' आईएल' का उपयोग कर शून्य पर इसे अस्वीकार करने की विधि को अस्वीकार कर दिया है, चाहे वे वर्चुअल हों या नहीं - 'कॉलवर्ट' में एक शून्य जांच शामिल है। अभी भी कुछ बार हैं जब 'कॉल' का उपयोग किया जाता है, और एक ऐसा होता है जब वैल्यूएटपेप ने वर्चुअल विधि को ओवरराइड कर दिया है - शून्य नहीं हो सकता है और आगे नहीं लिया जा सकता है, इसलिए 'कॉल' के पास वही अर्थशास्त्र होगा जो 'कॉलवर्ट' । अब, यह स्वयं ही दिखाता है कि वर्चुअल बनाम गैर-आभासी यह तय करने का एकमात्र तरीका नहीं है कि 'कॉलवर्ट' या' कॉल 'करना है, लेकिन यह विडंबना है कि सी # में उपयोग लगभग नाम के विपरीत है। –

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