Dynamically adding or removing items from a C# collection in a loop.
Submitted by Earok on Mon, 05/09/2011 - 19:41Bit of a random post this one.
Strictly speaking, there is no way to dynamically add or remove items from a Collection in a C# Foreach loop. There are at least three ways I know of that this can be faked though, do you know any others?
The "Right" Way
for(i = list.Count()-1;i>=0;i--)
{
item=list[i];
if (item.Delete) list.Remove(item);
}
This way cycles through the list backwards with a plain old For loop. Doing this forwards could be problematic if the size of the collection changes, but backwards should always be safe.
The "Easy" Way
foreach(var item in list.ToList())
{
if(item.Delete) list.Remove(item);
}
Simply create an entirely new list from the first one. I say "Easy" rather than "Right" as creating an entirely new list probably comes at a performance premium over the previous method (I haven't bothered with any benchmarking.) I generally prefer this pattern, it can also be useful in overcoming Linq-To-Entities limitations.
The "Strange" Way
var outList = new List(CustomObject);
foreach(var item in list)
{
if(!item.Delete) outList.Add(item);
}
list = outList;
I encountered this particular pattern in early versions of the Monkey programming language. Monkey originally had no way of removing items from a collection (No longer an issue), so the only way you could do it is to create a smaller list to supplant the larger one. This is probably the clumsiest and slowest of the three methods, but it has the unusual (but probably useless) advantage of not needing a remove method.
The Linq Way
list.RemoveAll(p=>p.Delete);
Completely forgot about Linq, which is the simplest as far as code goes. Though I haven't tested the previous code it should work fine. Thanks to Arran for pointing it out.
Comments
Tried use a bit of LINQ? :P
Hrn, every post is requiring captua..
Crap, forgot about Linq. Can you think of a better way to do it then the way I have just listed?
Also, Captcha should be gone, can you please confirm?
There are a couple of ways if you are going to accept to strange way.
for(int i=0;i<list.count.i++)
{
if(list[i].deleted)
{
list.RemoveAt(i--);
}
}
Nice