2011-11-20 13 views
50

डी कान सब, मुझे आश्चर्य है कि null का प्रकार सी # में शाब्दिक है?शून्य अक्षर का प्रकार क्या है?

जावा में, null शाब्दिक is of the special null type:

भी एक विशेष अशक्त प्रकार, अभिव्यक्ति null, जो कोई नाम नहीं है के प्रकार है। चूंकि शून्य प्रकार का कोई नाम नहीं है, इसलिए शून्य प्रकार के चर को घोषित करना या शून्य प्रकार पर डालना असंभव है। शून्य संदर्भ नल प्रकार की अभिव्यक्ति का एकमात्र संभावित मूल्य है। शून्य संदर्भ हमेशा किसी संदर्भ प्रकार में डाला जा सकता है।

सी ++ 11 में, वहाँ nullptr, जो is of type std::nullptr_t (पुराने साथी NULL की सिफारिश की संस्करण) है।

मैंने एमएसडीएन को सी # के बारे में खोजा, लेकिन specification इसके बारे में कुछ भी नहीं कहता है।

+3

मैं बिल्कुल एक प्रकार के रूप में शून्य का वर्णन नहीं करता। – ChaosPandion

+0

@ChosPandion: तो, सी # नहीं _every_ अभिव्यक्ति में एक प्रकार है? – Vlad

+1

वैसे मैं स्पष्ट रूप से गलत हूं। – ChaosPandion

उत्तर

53

ECMA C# language specification के अनुसार:

9.4.4.6 अशक्त शाब्दिक:

एक अशक्त-शाब्दिक के प्रकार अशक्त प्रकार है (§11.2.7)।

11.2.7 अशक्त प्रकार:

अशक्त शाब्दिक (§9.4.4.6) शून्य मान, जो प्रयोग किया जाता है एक संदर्भ निरूपित करने के लिए किसी भी वस्तु या सरणी पर इशारा करते हुए नहीं करने के लिए मूल्यांकन करता है, या किसी मान की अनुपस्थिति। शून्य प्रकार में एक मान है, जो शून्य मान है। इसलिए एक अभिव्यक्ति जिसका प्रकार शून्य प्रकार केवल शून्य मान का मूल्यांकन कर सकता है। स्पष्ट रूप से लिखने का कोई तरीका नहीं है और इसलिए, घोषित प्रकार में इसका उपयोग करने का कोई तरीका नहीं है। इसके अलावा, अशक्त प्रकार कभी नहीं प्रकार एक प्रकार पैरामीटर लिए लगाए गए अनुमान किया जा सकता है (§25.6.4)

तो अपने सवाल का जवाब देने, अशक्त यह खुद प्रकार है - अशक्त प्रकार।

हालांकि यह अजीब है कि यह कैसे C# 4.0 language specification या C# 3.0 language specification में उल्लेख नहीं किया है, लेकिन overview of C# 3.0 में बताया गया है, ECMA C# language specification और C# 2.0 language specification

+0

पर्याप्त अजीब, दस्तावेज़ में ईसीएमए मानक बिंदुओं का आपका संदर्भ जो एमएसडीएन में एक जैसा नहीं है: http://msdn.microsoft.com/en-us/library/ms228593.aspx – Vlad

+0

@Vlad यह काफी रोचक है, यह देखने लायक हो सकता है कि [एरिक लिपर्ट] (http://blogs.msdn.com/b/ericlippert/) इसके बारे में कहना है। –

+0

मुझे लगता है कि 'शून्य' के लिए एक अलग प्रकार रखने का तर्क जावा/सी ++ के समान है। मुझे आश्चर्य है कि क्यों इसे एमएसडीएन में नहीं मिला। – Vlad

42

अद्यतन: This question was the subject of my blog in July 2013. महान प्रश्न के लिए धन्यवाद!


J.Kommer के जवाब (क्या जाहिर कल्पना खुदाई का एक बहुत था! करने के लिए और उन पर अच्छा), लेकिन मैंने सोचा कि मैं एक छोटे से ऐतिहासिक परिप्रेक्ष्य जोड़ना होगा सही है।

जब मैड्स और मैं सी # 3.0 के विनिर्देश के विभिन्न हिस्सों के सटीक शब्दों को हल कर रहे थे तो हमें एहसास हुआ कि "शून्य प्रकार" विचित्र था। यह केवल एक मान के साथ एक "प्रकार" है। यह एक "प्रकार" है कि प्रतिबिंब के बारे में कुछ भी नहीं जानता है। यह एक "प्रकार" है जिसका नाम नहीं है, कि GetType कभी वापस नहीं आती है, कि आप स्थानीय चर या फ़ील्ड या किसी भी प्रकार के प्रकार के रूप में निर्दिष्ट नहीं कर सकते हैं।संक्षेप में, यह वास्तव में एक "प्रकार" है जो टाइप सिस्टम को "पूर्ण" बनाने के लिए है, ताकि प्रत्येक संकलन-समय अभिव्यक्ति में एक प्रकार हो।

सिवाय इसके कि सी # में पहले से ही अभिव्यक्तियां थीं जिनके पास कोई प्रकार नहीं था: सी # 1.0 में विधि समूह, सी # 2.0 में अज्ञात विधियां और सी # 3.0 में लैम्बडास में कोई प्रकार नहीं है। यदि उन सभी चीजों में कोई प्रकार नहीं हो सकता है, तो हमें एहसास हुआ कि "शून्य" के पास एक प्रकार की आवश्यकता नहीं है। इसलिए हमने सी # 3.0 में बेकार "शून्य प्रकार" के संदर्भ हटा दिए।

एक कार्यान्वयन विस्तार के रूप में, सी # 1.0 के माध्यम से 5.0 के माइक्रोसॉफ्ट कार्यान्वयन में सभी के पास "शून्य प्रकार" का प्रतिनिधित्व करने के लिए एक आंतरिक वस्तु है। उनके पास गैर-मौजूदा प्रकार के लैम्ब्डा, अज्ञात विधियों और विधि समूहों का प्रतिनिधित्व करने के लिए वस्तुएं भी हैं। इस कार्यान्वयन विकल्प में कई पेशेवर और विपक्ष हैं। प्रो पक्ष पर, संकलक किसी भी अभिव्यक्ति के प्रकार के लिए पूछ सकता है और एक जवाब प्राप्त कर सकते हैं। कॉन साइड पर, इसका मतलब है कि कभी-कभी प्रकार के विश्लेषण में बग जो वास्तव में कंपाइलर को क्रैश कर लेते हैं, इसके बजाय कार्यक्रमों में अर्थपूर्ण परिवर्तन होते हैं। इसका मेरा पसंदीदा उदाहरण यह है कि अवैध अभिव्यक्ति "शून्य ?? शून्य" का उपयोग करने के लिए सी # 2.0 में संभव है; एक बग के कारण संकलक ?? ऑपरेटर के गलत उपयोग के रूप में इसे ध्वजांकित करने में विफल रहता है, और यह अनुमान लगाता है कि इस अभिव्यक्ति का प्रकार "शून्य प्रकार" है, भले ही यह शून्य शब्दशः न हो। तब यह कई अन्य डाउनस्ट्रीम बग का कारण बनता है क्योंकि टाइप विश्लेषक इस प्रकार की समझ को समझने की कोशिश करता है।

रोज़लिन में हम शायद इस रणनीति का उपयोग नहीं करेंगे; बल्कि, हम बस संकलक कार्यान्वयन में सेंकना होगा कि कुछ अभिव्यक्तियों में कोई प्रकार नहीं है।

+2

मुझे उम्मीद थी कि रोज़लिन यह पूछने में सक्षम होगा कि किसी भी अभिव्यक्ति का प्रकार क्या है, और उन सभी गैर-प्रकार के प्रकारों के लिए प्रकार परिभाषाएं जोड़ देगा। आप इस सवाल का जवाब कैसे देंगे "अभिव्यक्ति 'नल' किस प्रकार है?" – configurator

+0

@Eric: लेकिन आधिकारिक माइक्रोसॉफ्ट की स्थिति क्या है? क्या 'शून्य' अभिव्यक्ति का एक प्रकार है? (यह आश्चर्यजनक नहीं हो सकता है अगर ऐसा नहीं होता है, तो यह ध्यान में रखते हुए कि लैम्बडा आदि में कोई प्रकार नहीं है।) – Vlad

+6

@Vlad: सी # 3 के रूप में आधिकारिक स्थिति।0 है कि "शून्य" में कोई प्रकार नहीं है। –

0

कोई रनटाइम प्रकार होने के बावजूद, null संकलन समय पर एक प्रकार में डाला जा सकता है, क्योंकि यह उदाहरण दिखाता है।

क्रम में, आप पा सकते हैं कि चर stringAsObject एक string, न केवल एक object रखती है, लेकिन आप चर के लिए किसी भी प्रकार के nullString और nullStringAsObject नहीं मिल रहा।

public enum Answer { Object, String, Int32, FileInfo }; 
private Answer GetAnswer(int i) { return Answer.Int32; } 
private Answer GetAnswer(string s) { return Answer.String; } 
private Answer GetAnswer(object o) { return Answer.Object; } 

[TestMethod] 
public void MusingAboutNullAtRuntimeVsCompileTime() 
{ 
    string nullString = null; 
    object nullStringAsObject = (string)null; 
    object stringAsObject = "a string"; 

    // resolved at runtime 
    Expect.Throws(typeof(ArgumentNullException),() => Type.GetTypeHandle(nullString)); 
    Expect.Throws(typeof(ArgumentNullException),() => Type.GetTypeHandle(nullStringAsObject)); 
    Assert.AreEqual(typeof(string), Type.GetTypeFromHandle(Type.GetTypeHandle(stringAsObject))); 
    Assert.AreEqual(typeof(string), stringAsObject.GetType()); 

    // resolved at compile time 
    Assert.AreEqual(Answer.String, this.GetAnswer(nullString)); 
    Assert.AreEqual(Answer.Object, this.GetAnswer(nullStringAsObject)); 
    Assert.AreEqual(Answer.Object, this.GetAnswer(stringAsObject)); 
    Assert.AreEqual(Answer.Object, this.GetAnswer((object)null)); 
    Assert.AreEqual(Answer.String, this.GetAnswer((string)null)); 
    Assert.AreEqual(Answer.String, this.GetAnswer(null)); 
} 

// Uncommenting the following method overload 
// makes the last statement in the test case ambiguous to the compiler 
// private Answer GetAnswer(FileInfo f) { return Answer.FileInfo; }