2010-08-23 11 views
9

foreach लूप केवल पढ़ने के लिए लूप क्यों है? इसके लिए क्या कारण हैं?मैं फ़ोरैच में लूप चर को क्यों संशोधित नहीं कर सकता?

+1

मुझे यकीन नहीं है कि एक रीडोनली लूप द्वारा आपका क्या मतलब है। क्या आप इस तथ्य का जिक्र कर रहे हैं कि आपको लूप के पुनरावृत्ति चर को संशोधित नहीं करना चाहिए? Ie myitems item.property = कुछ अगले – Tommy

+0

में प्रत्येक आइटम के लिए मुझे नहीं पता कि फॉर-लूप को केवल पढ़ने की अवधारणा को कैसे लागू किया जाए। या क्या आपका मतलब है कि वे कहते हैं कि यह केवल पढ़ने के लिए है? – helios

+2

यदि आप गणना के बारे में बात कर रहे हैं - हाँ! आप उस गणना को नहीं बदल सकते जिसे आप लूप कर रहे हैं। –

उत्तर

22

मुझे यकीन है कि आप एक "केवल पढ़ने के लिए लूप" द्वारा कि वास्तव में क्या मतलब है नहीं कर रहा हूँ, लेकिन मेरा अनुमान है कि यह है कि आप को पता है कि ऐसा क्यों संकलन नहीं करता हैं:

int[] ints = { 1, 2, 3 }; 
foreach (int x in ints) 
{ 
    x = 4; 
} 

ऊपर कोड निम्नलिखित दे देंगे संकलन त्रुटि:

 
Cannot assign to 'x' because it is a 'foreach iteration variable' 

यह अस्वीकृत क्यों है? इसे असाइन करने की कोशिश करने से शायद आप जो भी चाहते हैं वह नहीं करेंगे - यह मूल संग्रह की सामग्री को संशोधित नहीं करेगा। ऐसा इसलिए है क्योंकि परिवर्तनीय एक्स सूची में तत्वों का संदर्भ नहीं है - यह एक प्रति है। बग्गी कोड लिखने वाले लोगों से बचने के लिए, कंपाइलर इसे अस्वीकार करता है।

+0

+1। यह कहने के समान है 'Foo x = new Foo(); फू वाई = एक्स; y = new foo(); 'y' को 'new foo') पर सेट करना' x' के लिए कुछ भी नहीं है। इसी तरह, आपके लूप चर के रूप में 'foo' होने और' foo = new foo(); '(यदि आप ** कर सकते हैं) कह रहे हैं तो संग्रह में' Foo' के लिए कुछ भी नहीं है। –

+1

यह है (प्रतिलिपि भाग) संदर्भ प्रकार के लिए सही नहीं है तो x IENumerable –

+0

@Rune FS में ऑब्जेक्ट का संदर्भ रखेगा: संदर्भ प्रकारों के मामले में यह संदर्भ की * प्रति * है। यहां तक ​​कि इस मामले में यह संभवतया वह नहीं करेगा जो आप चाहते थे यदि आप इसे असाइन कर सकें। –

5

मुझे लगता है कि यह कैसे हैटरेटर सूची के माध्यम से यात्रा करता है।

आपको लगता है कि कैसे निपटेंगे

Alaska 
Nebraska 
Ohio 

foreach(var s in States) 
{ 
} 

के बीच में आप एक States.Add कर ("मिसौरी"):

आप एक क्रमबद्ध सूची है कहो? यदि आप पहले से ही उस इंडेक्स से पहले हैं तो भी मिसौरी पर जाएं।

+0

iEnumerable के लिए माइक्रोसॉफ्ट का अनुबंध कहता है कि iEnumerable को संग्रह को अद्यतन करने के किसी भी साधन को प्रदान नहीं किया जाना चाहिए, अगले तत्व की गणना। अगर मेरे ड्रूटर थे, तो आपके परिदृश्य में एक गणक मिसिसिपी को शामिल करने या शामिल करने के लिए स्वतंत्र नहीं होगा, लेकिन गणना के दौरान मौजूद सभी तत्वों को ठीक करने के लिए या फिर अपवाद फेंकने की आवश्यकता होगी यदि यह ऐसा नहीं कर सका। – supercat

3

, यदि यह द्वारा, क्या आपका मतलब है:

Why shouldn't I modify the collection that's being foreach 'd over?

कोई प्रतिभू है कि आइटम है कि आप किसी दिए गए आदेश में बाहर आ रही हैं, और कि एक आइटम जोड़ने, या किसी आइटम को हटाने नहीं होगा संग्रह में वस्तुओं का क्रम बदलने के लिए, या यहां तक ​​कि गणनाकर्ता भी अमान्य बनने का कारण बनता है।

कल्पना कीजिए यदि आप निम्न कोड भाग गया: जैसे ही आप पाश मारा मैं जहां 6 (अर्थात के बाद आइटम निकाल दिया जाता है) कुछ भी हो सकता है

var items = GetListOfTOfSomething(); // Returns 10 items 

int i = 0; 
foreach(vat item in items) 
{ 
    i++; 
    if (i == 5) 
    { 
     items.Remove(item); 
    } 
} 

। किसी आइटम को हटाने के कारण गणनाकर्ता को अमान्य कर दिया गया हो सकता है, सबकुछ अंतर्निहित संग्रह में "एक से घिरा हुआ" हो सकता है जिसके कारण किसी आइटम को निकाले गए स्थान का स्थान लेना पड़ता है, जिसका अर्थ है कि आप "छोड़ें"।

यदि आप मतलब था "क्यों नहीं मैं बदल सकते हैं मूल्य है कि प्रत्येक यात्रा पर प्रदान की जाती है" तो, अगर संग्रह आप के साथ काम कर रहे हैं value types होता है, कोई भी परिवर्तन संरक्षित नहीं किए जाएंगे, क्योंकि यह एक है जिस मूल्य के साथ आप काम कर रहे हैं, संदर्भ के बजाय।

0

foreachIEnumerable इंटरफ़ेस को लागू करने वाली सभी चीज़ों के साथ काम करता है। सिंक्रनाइज़ेशन समस्याओं से बचने के लिए, गणना करने के दौरान गणना करने योग्य नहीं किया जाएगा।

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

System.InvalidOperationException was unhandled 
    Message="Collection was modified; enumeration operation may not execute." 

foreach की कोशिश करता प्रत्येक यात्रा पर अगले आइटम जो मुसीबत पैदा कर सकता है अगर आप एक ही समय में एक और धागे से इसे संशोधित कर रहे हैं पाने के लिए।

1

foreach कमांड संग्रह के माध्यम से लूप के लिए IEnumerable इंटरफ़ेस का उपयोग करता है। इंटरफ़ेस केवल संग्रह के माध्यम से कदम उठाने और वर्तमान आइटम प्राप्त करने के लिए विधियों को परिभाषित करता है, संग्रह को अपडेट करने के लिए कोई विधि नहीं है।

क्योंकि इंटरफ़ेस केवल एक दिशा में कलेक्टर को पढ़ने के लिए आवश्यक न्यूनतम विधियों को परिभाषित करता है, इंटरफ़ेस संग्रह की विस्तृत श्रृंखला द्वारा कार्यान्वित किया जा सकता है।

जैसे ही आप एक समय में केवल एक ही आइटम तक पहुंचते हैं, पूरे संग्रह को एक ही समय में मौजूद नहीं होना चाहिए। यह उदाहरण के लिए LINQ अभिव्यक्तियों द्वारा उपयोग किया जाता है, जहां यह फ्लाई पर परिणाम बनाता है जैसा कि आप इसे पढ़ते हैं, पहले पूरे परिणाम को बनाने के बजाय और फिर आप इसे लूप करते हैं।

1

सुनिश्चित नहीं है कि केवल पढ़ने के लिए आपका क्या मतलब है, लेकिन मुझे लगता है कि फोरच लूप हुड के नीचे क्या है, यह समझने में मदद मिलेगी। आप संग्रह (सूची) बदलते हैं तो यह असंभव करने के लिए कठिन हो रही है कैसे यात्रा पर कार्रवाई करने के यह पता लगाने की

IEnumerator enumerator = list.GetEnumerator(); 
while(enumerator.MoveNext()) 
{ 
    T element = enumerator.Current; 
    //body goes here 
} 

: यह वाक्यात्मक चीनी है और यह भी कुछ इस तरह लिखा जा सकता है। तत्व (फ़ोरैच संस्करण में) को असाइन करने के लिए या तो गणनाकर्ता को असाइन करने का प्रयास करने के रूप में देखा जा सकता है। वर्तमान जो केवल पढ़ने के लिए या स्थानीय स्तर के मूल्य को बदलने के लिए प्रतिबिंबित करने का प्रयास कर रहा है। वर्तमान में आप जो भी परिचय दे सकते हैं एक स्थानीय स्वयं क्योंकि अब इसकी गणना की गई सूची के साथ अब कुछ भी नहीं है।

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