2012-07-10 7 views
10

महान आश्चर्य मैं आज निम्नलिखित व्यवहार मनाया के साथ: एक वर्गबदलने गुण .Current

class Foo 
{ 
    prop int FooNumber { get; set; } 
} 

और इस कोड को देखते हुए

IEnumerable<Foo> foos = Enumerable.Range(0,3).Select(new Foo()); 

foreach (var foo in foos) 
    foo.Bar = 5; 

foreach (var foo in foos) 
    Console.Write(foo.Bar); // Writes 000 

जबकि आरंभ new List<Foo>{ new Foo(), new Foo(), new Foo() } करने के लिए foos पाश लिखने बनाता है " 555 "।

मेरा प्रश्न: ऐसा क्यों होता है और वहाँ (है, जो एक टिप्पणी की जरूरत है, क्योंकि यह यहाँ की जरूरत हो प्रतीत नहीं होता है) इस whithout .ToList() का उपयोग कर नाकाम करने के लिए एक रास्ता है है।

+4

रेसर्पर "संभावित एकाधिक गणना" कहने वाली अद्भुत दुनिया में आपका स्वागत है। एक गणना योग्य ** नहीं ** संग्रह है। तथ्य यह है कि कभी-कभी एक गणना एक संग्रह पर है और आप इसके नीचे संशोधित कर सकते हैं एक साइड इफेक्ट है। –

उत्तर

20

यह इसलिए होता है क्योंकि foos गतिशील रूप से प्रत्येक बार जब आप इसे गणना का उत्पादन किया है। तो पहले पुनरावृत्ति के दौरान आप उन वस्तुओं पर संपत्ति मान सेट कर रहे हैं जिन्हें पुनरावृत्ति समाप्त होने के बाद किसी भी चीज़ द्वारा संदर्भित नहीं किया जाता है। दूसरा पुनरावृत्ति ताजा निर्मित वस्तुओं पर काम करता है जिनमें डिफ़ॉल्ट संपत्ति मूल्य होता है।

"लगातार" वस्तुओं की एक सूची के लिए foos आरंभ किया जा रहा चीजें बदल जाता है, के रूप में ही कारण के लिए .ToList() का उपयोग कर करता है (एक "स्थिर" सूची का निर्माण किया और दो बार से अधिक दोहराया है; मूल गतिशील उत्पादित IEnumerable केवल एक बार से अधिक दोहराया जाता है)।

की स्थापना के बाद कि आप .ToList() यहाँ का उपयोग करना चाहिए: सामान्य रूप में मैं नहीं लग रहा है कि क्योंकि यह गतिशील रूप से उत्पादित दृश्यों एक बार से अधिक से अधिक पुनरावृति करने के लिए प्रथागत नहीं है, यह एक टिप्पणी की जरूरत है (मैं कई कोड विश्लेषण उपकरण इस के खिलाफ चेतावनी दी है विश्वास करते हैं), लेकिन हर तरह से एक लिखो।

+0

यह बताता है, धन्यवाद। मैं झूठी छाप के तहत था, कि पहली गणना के बाद, परिणाम कहीं भी संग्रहीत किया जाएगा। – Jens

3

यह स्पष्ट लगता क्या हो रहा है: हर बार जब आप की गणना, आप नए फू वस्तुओं instantiating रहे हैं।

आप संपत्ति मूल्यों (Foo.Bar) संरक्षित करने की है, तो आप रखने के लिए फू के कहीं, और ToList() ऐसा करने का एक आसान तरीका है करने जा रहे हैं चाहते हैं।