August 2007 - Posts

This issue seems to be raised a lot in the newsgroups. When you iterate a container, ArrayList for instance, you cannot remove items in the contain inside the body of the loop. You get a nasty exception if you have no regard for the rules.

Apparently, the run-time imposes a read-only restriction on the iterating container. The read-only restriction forces all assumptions about the container to be valid during the loop iteration process. There's an article here that discusses this in more detail.

Basically, this code produces an exception:

//arr is an arraylist with some random items
foreach (string s in arr)
 {
        arr.Remove(s);
}

whereas this code does not:

//notice the inline declaration of the ArrayList in the loop
foreach (string s in new System.Collections.ArrayList(arr))
{
       arr.Remove(s);
}

However, I did get yelled at for providing a solution that was not efficient :-).

To be fair, the solution discussed in this article is mildly inefficient; it takes well under a second to remove 10000 items from a collection. If efficiency is your main issue, you may want to make use of the generics approach. The generics approach will follow this approach:

List<string> list = new List<string>();
//add list items
...
list.RemoveAt(find);
//define find here
public bool find(string s)
{
      //add some condition here, for now return true
      return true
}

To be clear, the generic approach is much faster at the expense of more code. There is no free cheese. However, because both of these approaches execute in well under a second, you earn your daily wage by focusing on other inefficient points in your application such as indexing your database records. It's not worth it to optimize away 0.5 seconds for this routine while your database records run on stale indices for instance. That's pretty pointless in my humble opinion.

Something of interest to note is that while the underlying implementation of remove is implemented with a linear search followed by a delete, the generic approach also uses a linear search using the find method. But it is important to note that this linear search is a one-time expense. This sweep marks all items for deletion and then removes them in one pass. My approach essentially incurs this expense every time remove is called. This explains the jump in performance by the generics approach.

 In the real world, you won't get any brownie points for that optimization. Period. Go find somewhere else in your application to spend time and energy on.