परिचय: यह वह त्रुटि है जिसने लाखों बार कोड तोड़ा है
\n\nक्या आपने कभी एक सरल foreach लिखा, प्रोग्राम चलाया, और अचानक — बैम! — InvalidOperationException डरावने संदेश के साथ आता है: "Collection was modified; enumeration operation may not execute"? यदि हाँ, तो आप अकेले नहीं हैं। Stack Overflow पर इस प्रश्न को हज़ारों बार देखा गया है, और इसे नौसिखिए और अनुभवी डेवलपर्स दोनों पूछते हैं।
इस लेख में, हम समझेंगे कि यह त्रुटि क्यों होती है, इसे कैसे दोहराया जाए, और सबसे महत्वपूर्ण बात — इसे कैसे टाला जाए। हम तीन सिद्ध तरीकों पर विचार करेंगे, C# में वास्तविक कोड लिखेंगे और आपको एक स्पष्ट कार्य योजना देंगे। चलिए शुरू करते हैं!
\n\n"Collection was modified" क्या है? त्रुटि का विश्लेषण
\n\nCollection was modified; enumeration operation may not execute त्रुटि InvalidOperationException प्रकार का एक अपवाद है, जो तब फेंका जाता है जब आप foreach या किसी अन्य गणक (IEnumerator) का उपयोग करके संग्रह की गणना के दौरान उसे बदलने (तत्व जोड़ने, हटाने या बदलने) का प्रयास करते हैं।
कल्पना करें कि आप एक किताब पढ़ रहे हैं, और कोई उसी समय उसमें से पन्ने फाड़ रहा है। आप भ्रमित हो जाते हैं, समझ नहीं पाते कि आगे क्या पढ़ें। गणक के साथ भी ऐसा ही होता है: यह नहीं जानता कि कैसे जारी रखना है यदि संग्रह चलते-फिरते बदलता है।
\n\nत्रुटि उत्पन्न करने वाला कोड कैसा दिखता है?
\nयहाँ एक क्लासिक उदाहरण है जो निश्चित रूप से त्रुटि की ओर ले जाएगा:
\n\nList<string> fruits = new List<string> { "apple", "banana", "cherry", "date" };\n\nforeach (var fruit in fruits)\n{\n if (fruit == "banana")\n {\n fruits.Remove(fruit); // त्रुटि! Collection was modified\n }\n}\n\nइस कोड को चलाएँ — और दूसरे पुनरावृत्ति पर आपको InvalidOperationException मिलेगा। क्यों? क्योंकि foreach एक आंतरिक गणक का उपयोग करता है जो ट्रैवर्सल के दौरान संग्रह में बदलाव को रोकता है।
ऐसा क्यों होता है? C# के अंदर झाँकें
\n\nजब आप foreach लिखते हैं, C# कंपाइलर इसे GetEnumerator() विधि के कॉल में बदल देता है। यह विधि एक IEnumerator ऑब्जेक्ट लौटाती है जो ट्रैवर्सल की स्थिति (वर्तमान इंडेक्स, संग्रह का संस्करण) संग्रहीत करता है। हर बार जब संग्रह बदलता है (Add, Remove, Clear आदि के माध्यम से), इसका आंतरिक संस्करण काउंटर बढ़ जाता है। गणक प्रत्येक चरण पर इस संस्करण की जाँच करता है। यदि यह मेल नहीं खाता — तो अपवाद फेंका जाता है।
यह अनिश्चित व्यवहार से बचाने के लिए किया गया है। कल्पना करें कि आप सूची के बीच से एक तत्व हटाते हैं: बाद के सभी तत्वों के इंडेक्स बदल जाते हैं, और गणक एक तत्व को छोड़ सकता है या एक ही तत्व को दो बार संसाधित कर सकता है। .NET डेवलपर्स ने फैसला किया कि एक अदृश्य तार्किक त्रुटि की अनुमति देने से बेहतर है कि अपवाद फेंका जाए।
\n\n"Collection was modified" त्रुटि से बचने के शीर्ष 3 तरीके
\n\nअब जब हम दुश्मन को पहचान गए हैं, तो आइए जानें कि उसे कैसे हराया जाए। तीन मुख्य दृष्टिकोण हैं, और प्रत्येक विभिन्न स्थितियों के लिए उपयुक्त है।
\n\nतरीका 1: गणना से पहले संग्रह की प्रतिलिपि बनाना
\nसबसे सरल और सुरक्षित तरीका — संग्रह की एक प्रतिलिपि बनाएँ और उस पर गणना करें, जबकि मूल में बदलाव करें।
\n\nList<string> fruits = new List<string> { "apple", "banana", "cherry", "date" };\n\n// गणना के लिए सूची की प्रतिलिपि बनाएँ\nforeach (var fruit in fruits.ToList()) // या new List<string>(fruits)\n{\n if (fruit == "banana")\n {\n fruits.Remove(fruit); // अब यह सुरक्षित है\n }\n}\n\nConsole.WriteLine(string.Join(", ", fruits)); // आउटपुट: apple, cherry, date\n\nलाभ: सरलता, पठनीयता, छोटे संग्रहों के लिए उपयुक्त।
\nनुकसान: अतिरिक्त मेमोरी की आवश्यकता, बड़ी सूचियों के लिए धीमा हो सकता है।
सुझाव: मे