2009-09-23 13 views
10

निम्न कोड को संकलित करता है, लेकिन एक NullReferenceException के साथ विफल:सी # शब्दकोश प्रारंभकर्ता संकलन विसंगति

class Test 
{ 
    public Dictionary<string, string> Dictionary { get; set; } 
} 

static void Main(string[] args) 
{ 
    var x = new Test 
    { 
     Dictionary = // fails 
     { 
      { "key", "value" }, { "key2", "value2" } 
     } 
    }; 
} 

आप लाइन निम्नलिखित के साथ चिह्नित 'विफल रहता है' की जगह ले रहे हैं, तो यह काम करता है (उम्मीद के रूप में):

Dictionary = new Dictionary<string, string> 

क्या असफल वाक्यविन्यास का कोई उद्देश्य है - क्या इसे किसी अन्य मामले में सफलतापूर्वक उपयोग किया जा सकता है? या यह संकलक में एक निरीक्षण है?

उत्तर

32

नहीं, यह एक गलती नहीं है ... यह प्रारंभ वाक्य रचना :) की अपनी समझ में एक दोष है

Dictionary = { ... } 

के विचार मामलों में जहां फोन करने वाले तक पढ़ने की पहुंच है के लिए है एक संग्रह संपत्ति के लिए, लेकिन पहुंच लिखें। दूसरे शब्दों में, इस तरह की स्थितियां:

class Test 
{ 
    private readonly Dictionary<string, string> dictionary 
     = new Dictionary<string, string>(); 
    public Dictionary<string, string> Dictionary { get { return dictionary; } } 
} 

असल में यह जोड़ने के लिए कॉल होने पर समाप्त होता है, लेकिन पहले कोई नया संग्रह बनाये बिना। तो यह कोड:

Test test = new Test { Dictionary = { { "a", "b"}, {"c", "d" } }; 

के बराबर है:

Test tmp = new Test(); 
Dictionary<string, string> tmpDictionary = tmp.Dictionary; 
tmpDictionary.Add("a", "b"); 
tmpDictionary.Add("c", "d"); 
Test test = tmp; 

जहां इसके उपयोगी होने का एक अच्छा उदाहरण है यूआई के लिए Controls संग्रह के साथ है। आप ऐसा कर सकते हैं:

Form form = new Form 
{ 
    Controls = 
    { 
     new Button { Text = "Hi" }, 
     new TextBox { Text = "There" } 
    } 
}; 

लेकिन आप नहीं वास्तव में सेट कर सकते हैं Controls संपत्ति, है क्योंकि यह केवल पढ़ने के लिए।

+0

तो इसका उपयोग कन्स्ट्रक्टर द्वारा बनाए गए शब्दकोश में आइटम जोड़ने के लिए किया जाता है - मुझे यह महसूस करना चाहिए था। लेकिन यह बराबर ऑपरेटर का एक अजीब उपयोग है, क्योंकि प्रभाव जो भी पहले से ही शब्दकोश में जोड़ना है (कन्स्ट्रक्टर ने पहले आइटम जोड़े होंगे)। –

+0

सॉर्ट करें, हां ... लेकिन साथ ही इसका उपयोग संग्रह में प्रारंभिक मान सेट करने के लिए किया जाता है, इसलिए यह इस तरह से फिट बैठता है। –

+0

दाएं। गायब 'नया' लाल झंडा होना चाहिए .. लेकिन इस वाक्यविन्यास का कभी भी उपयोग नहीं किया, मैंने बराबर ऑपरेटर को भी सचमुच लिया। –

0

यह एक शून्य संदर्भ अपवाद के साथ विफल रहता है क्योंकि आपने एक परिवर्तनीय (शब्दकोश) घोषित किया है जो अनियमित है, इसलिए यह शून्य है।

जब आप प्रारंभकर्ता सिंटैक्स का उपयोग करके इसमें प्रविष्टियां जोड़ने का प्रयास करते हैं, तो आप डेटा को एक शून्य ऑब्जेक्ट में लिखने की कोशिश कर रहे हैं।

जब आप "= new Dictionary ..." के साथ लाइन को प्रतिस्थापित करते हैं, तो आप संदर्भ के लिए शब्दकोश के लिए एक नई वस्तु बना रहे हैं, और इसलिए आप इसमें सफलतापूर्वक प्रविष्टियां जोड़ सकते हैं।

(जॉन स्कीट के उदाहरण में, नियंत्रण संग्रह पहले से ही फार्म द्वारा बनाई गई होगी, इसलिए यह ठीक काम करता है)

+0

हां, ज़ाहिर है। मेरा सवाल था: इस वाक्यविन्यास की अनुमति क्यों दें? –

+0

पर्याप्त मेला।जॉन ने आपके प्रश्न का उत्तर दिया, इसलिए मैंने सोचा कि अगर आप विफलता को समझ नहीं पाए तो मैं कारण भर दूंगा। –

4

तुम अब भी वाक्य रचना आप एक निर्माता में चाहते हैं का उपयोग कर सकते हैं:

Dictionary<string, string> dictionary = new Dictionary<string, string> 
      { 
       {"a", "b"}, 
       {"c", "d"} 
      }; 
संबंधित मुद्दे