1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

.Net collections enumeration

Discussion in 'C#' started by shabbir, Feb 19, 2008.

  1. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,293
    Likes Received:
    365
    Trophy Points:
    83

    Introduction



    I happen to edit the collections many times in the foreach loop and run into problems and then each time I got a different solution when going to Google, So first I would try to list each of the solution and then discuss them so that we all can have the best practice in the collection iteration. Please note that I am not saying the one I have mentioned is the best but I found it to be one of the best for my context.

    Background



    Recently I cam across an exception as Collection was modified; enumeration operation may not execute. and the sample code which can throw such exception is
    Code:
    ArrayList list = new ArrayList();
    list.Add("123");
    list.Add("456");
    list.Add("789");
    list.Add("741");
    list.Add("852");
    
    foreach (string s in list)
    {
        if (s == "789")
        {
            list.RemoveAt(list.IndexOf("789"));
        }
    }
    
    As a C++ background programmer I normally use to do the same in C++ with arrays and I continued the same in C-Sharp as well but ran into problem with the exception.

    Solution 1 : Convert collection to Array



    Code:
    foreach (string s in list.ToArray())
    {
        if (s == "789")
        {
            list.RemoveAt(list.IndexOf("789"));
        }
    }
    
    The method is not very efficient because you are not using the collection but using the arrays and is not good for large collections.

    Solution 2 : Use for loop instead foreach.


    Code:
    int cnt = list.Count - 1;
    for (int i = 0; i < cnt; )
    {
        string s = (string)list[i];
        System.Console.WriteLine(s);
        if (s == "789")
        {
            list.RemoveAt(i);
        }
        else
        {
            i++;
        }
    }
    
    There are many disadvantages to the above method. One being if you are removing then you should not increment the counter when you are removing or else you will miss the next element after the removed index. Here it would be 741 which is after 789 and the other one being you are always looping through the count -1 initially which is not the case when you add / remove it and so you need to take all the pain to make sure it loops as expected with lots of if's and else's.

    Solution 3 : Mark all the element.



    Mark all the elements you wish to remove and then iterate through the marked object to remove them.
    Code:
    ArrayList indexListToRemove = new ArrayList();
    foreach (string s in list)
    {
        if (s == "789")
        {
            indexListToRemove.Add(s);
        }
    }
    foreach (string s in indexListToRemove)
    {
        list.Remove(s);
    }
    

    Summary



    You should avoid changes to collections (in fact most cases you will not even be able to change the collection) using foreach.
     
  2. venkatesanj@hcl.in

    venkatesanj@hcl.in New Member

    Joined:
    Oct 19, 2007
    Messages:
    24
    Likes Received:
    1
    Trophy Points:
    0
    Shabbir,

    I think you dealt only with list collection. I will try to post my articles on other .net collections.

    Regards,
    Venkatesan Prabu. J
     
  3. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,293
    Likes Received:
    365
    Trophy Points:
    83
  4. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,293
    Likes Received:
    365
    Trophy Points:
    83
  5. aisha.ansari84

    aisha.ansari84 New Member

    Joined:
    Feb 13, 2008
    Messages:
    82
    Likes Received:
    1
    Trophy Points:
    0
    yes all the others are equivalently important
     
  6. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,293
    Likes Received:
    365
    Trophy Points:
    83

Share This Page