2010-01-07 17 views
62

मैं एक ArrayList से किसी आइटम को हटाने के लिए कोशिश कर रहा हूँ और मैं इस अपवाद प्राप्त करें:
Collection was modified; enumeration operation may not execute.संग्रह संशोधित किया गया था; गणन आपरेशन ArrayList में अमल नहीं हो सकता है

कोई भी विचार?

+11

रिकॉर्ड के लिए की तरह कोशिश कर सकते हैं जब तक आप नेट 1.0 या 1.1 का उपयोग कर रहे हैं, तो आप शायद 'सूची ' के बजाय 'ArrayList' का उपयोग करना चाहिए। –

+2

यह डुप्लिकेट मुझे यह त्रुटि क्यों मिलती है ** कभी-कभी ** 'आवेदन पर। एक्सिट();' और मैं किसी भी संग्रह और न ही अनुप्रयोग में हेरफेर करता हूं। – Bitterblue

+0

foreach (ItemCollection.Values ​​में ItemCollection आइटम) foreach के लिए (ItemCollection रों ItemCollection.Values.ToList में()) मुद्दा यह है कि ItemCollection.Values ​​foreach पाश अंदर संशोधित किया जा रहा है। कॉलिंग ItemCollection.Values.ToList() ग्राहकों के मूल्यों की प्रतिलिपि बनाता है। Foreach –

उत्तर

167

आप आइटम निकाल रहे हैं एक foreach दौरान, हाँ? बस, आप नहीं कर सकते।

  • पुनरावृति पीछे की ओर सूचकांक द्वारा, को हटाने के मिलान आइटम

    for(int i = list.Count - 1; i >= 0; i--) { 
        if({some test}) list.RemoveAt(i); 
    } 
    
  • उपयोग foreach,

    • उपयोग List<T> और RemoveAll विधेय के साथ और एक में मिलान आइटम डाल: वहाँ कुछ आम विकल्प यहाँ हैं दूसरी सूची; अब foreach के बजाय दूसरी सूची की गणना और पहले से उन वस्तुओं को हटाने (अगर आपको मैं क्या मतलब है)

  • +0

    +1, मेरे लिए बहुत तेज़ :) – Glenn

    +0

    मुझे लगता है कि आपका क्या मतलब है ... मैं इसे – Ricardo

    +4

    करने की कोशिश करूंगा यदि संग्रह इतना बड़ा नहीं है, तो एक सरल। ToArray() और यह अनुमान लगाता है कि इसके बजाय पर्याप्त हो सकता है भी। –

    5

    सूची के माध्यम से एक लूप के अंदर सूची को संशोधित न करें।

    इसके बजाय, for() या while() का उपयोग इंडेक्स के साथ करें, सूची के माध्यम से पीछे की ओर जाएं। (यह आप गलत सूचकांक प्राप्त किए बिना चीजों को नष्ट करने देगा।)

    var foo = new List<Bar>(); 
    
    for(int i = foo.Count-1; i >= 0; --i) 
    { 
        var item = foo[i]; 
        // do something with item 
    } 
    
    +1

    स्नैप की शुरुआत में एक अलग सूची में मूल्य! तो, मुझे यह कैसे करना चाहिए? – Ricardo

    +1

    इसके बजाय नियमित लूप का उपयोग करें (के लिए /)। समस्या 'foreach' कथन (यानी एक गणक) का उपयोग कर रही है। –

    +0

    @silky f आप संग्रह के माध्यम से पुनरावृत्त करने के लिए() या while() के लिए उपयोग कर रहे हैं, इसे वापस/शीर्ष से करना सुनिश्चित करें - संग्रह.count-1 से शुरू करना और 0 पर नीचे जाना। अन्यथा आप एक ही समस्या मारा। –

    2

    (), एक अंकीय सूचकांक के साथ एक के लिए() पाश का उपयोग करें।

    +0

    यदि आप इस दृष्टिकोण का उपयोग करते हैं तो आपको * पीछे की ओर गिनना चाहिए। –

    +2

    @Rob - नहीं * चाहिए *, लेकिन यदि आप आगे बढ़ते हैं तो यह मुश्किल है; इसे गलत करने और एक-एक करके समाप्त होने के अधिक तरीके। –

    +0

    एक विशिष्ट कोड नमूना सिर्फ एक स्पष्टीकरण की तुलना में अधिक वांछित है, जो इस के समाधान की तलाश में है। – theJerm

    8

    एक तरीका यह है कि आइटम को नई सूची में हटाया जाए। फिर उन वस्तुओं को छोड़ दें और हटाएं।

    +0

    इस तरह मैंने इसे संभाला और इस तरह कोड को पढ़ने के लिए यह बहुत स्पष्ट है। – Chris

    19

    यहाँ एक उदाहरण (कोई लेखन त्रुटि के लिए खेद है)

    var itemsToRemove = new ArrayList(); // should use generic List if you can 
    
    foreach (var item in originalArrayList) { 
        if (...) { 
        itemsToRemove.Add(item); 
        } 
    } 
    
    foreach (var item in itemsToRemove) { 
        originalArrayList.Remove(item); 
    } 
    

    या आप 3.5 उपयोग कर रहे हैं है, Linq पहले थोड़ा आसान बनाता है:

    itemsToRemove = originalArrayList 
        .Where(item => ...) 
        .ToArray(); 
    
    foreach (var item in itemsToRemove) { 
        originalArrayList.Remove(item); 
    } 
    

    के साथ बदलें "..." अपने शर्त यह निर्धारित करती है कि आइटम को हटाया जाना चाहिए या नहीं।

    +1

    यदि आप "सामान्य सूची" का उपयोग कर रहे हैं (जिसे मैं 'सूची ' के रूप में समझता हूं) तो बस 'list.RemoveAll (item => ...) 'का उपयोग करें। –

    7

    मुझे for लूप का उपयोग करके पीछे हटाना पसंद है, लेकिन यह foreach की तुलना में कठिन हो सकता है। एक समाधान जिसे मैं पसंद करता हूं वह एक गणक बनाना है जो सूची को पिछड़ा करता है। आप इसे ArrayList या List<T> पर एक विस्तार विधि के रूप में कार्यान्वित कर सकते हैं। ArrayList के लिए कार्यान्वयन नीचे है।

    public static IEnumerable GetRemoveSafeEnumerator(this ArrayList list) 
        { 
         for (int i = list.Count - 1; i >= 0; i--) 
         { 
          // Reset the value of i if it is invalid. 
          // This occurs when more than one item 
          // is removed from the list during the enumeration. 
          if (i >= list.Count) 
          { 
           if (list.Count == 0) 
            yield break; 
    
           i = list.Count - 1; 
          } 
    
          yield return list[i]; 
         } 
        } 
    

    List<T> के लिए कार्यान्वयन समान है।

    public static IEnumerable<T> GetRemoveSafeEnumerator<T>(this List<T> list) 
        { 
         for (int i = list.Count - 1; i >= 0; i--) 
         { 
          // Reset the value of i if it is invalid. 
          // This occurs when more than one item 
          // is removed from the list during the enumeration. 
          if (i >= list.Count) 
          { 
           if (list.Count == 0) 
            yield break; 
    
           i = list.Count - 1; 
          } 
    
          yield return list[i]; 
         } 
        } 
    

    नीचे दिए गए उदाहरण एक ArrayList से सभी भी पूर्णांकों दूर करने के लिए प्रगणक उपयोग करता है।

    ArrayList list = new ArrayList() {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; 
    
        foreach (int item in list.GetRemoveSafeEnumerator()) 
        { 
         if (item % 2 == 0) 
          list.Remove(item); 
        } 
    
    2

    मैं अंक मैं इस पोस्ट में पढ़ा है के कई के साथ सहमत हैं और मैं मूल पोस्टिंग के रूप में ठीक उसी मुद्दे को हल करने के लिए अपने समाधान में उन्हें शामिल किया गया है।

    जिसके अनुसार, टिप्पणियां मैं सराहना कर रहे हैं: "। जब तक आप नेट 1.0 1.1 का उपयोग कर रहे या, ArrayList के बजाय List<T> का उपयोग करें"

    • "इसके अलावा, (आइटम जोड़ने एस) को एक नई सूची में हटाया जाना चाहिए। फिर उन वस्तुओं को हटाएं और हटाएं। " .. मेरे मामले में मैंने अभी एक नई सूची बनाई है और इसे वैध डेटा मानों के साथ पॉप्युलेट किया है।

    उदा।

    private List<string> managedLocationIDList = new List<string>(); 
    string managedLocationIDs = ";1321;1235;;" // user input, should be semicolon seperated list of values 
    
    managedLocationIDList.AddRange(managedLocationIDs.Split(new char[] { ';' })); 
    List<string> checkLocationIDs = new List<string>(); 
    
    // Remove any duplicate ID's and cleanup the string holding the list if ID's 
    Functions helper = new Functions(); 
    checkLocationIDs = helper.ParseList(managedLocationIDList); 
    
    ... 
    public List<string> ParseList(List<string> checkList) 
    { 
        List<string> verifiedList = new List<string>(); 
    
        foreach (string listItem in checkList) 
        if (!verifiedList.Contains(listItem.Trim()) && listItem != string.Empty) 
         verifiedList.Add(listItem.Trim()); 
    
        verifiedList.Sort(); 
        return verifiedList; 
    }   
    
    4

    क्या मुझे कुछ याद आ रही है? अगर मैं गलत हूं तो कोई मुझे सही करेगा।

    list.RemoveAll(s => s.Name == "Fred"); 
    
    1

    ArrayList का उपयोग कर भी आप, इस

    ArrayList arraylist = ... // myobject data list 
    
    ArrayList temp = (ArrayList)arraylist.Clone(); 
    
    foreach (var item in temp) 
    { 
         if (...) 
         arraylist.Remove(item); 
    } 
    
    संबंधित मुद्दे

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