Pages

Wednesday, May 29, 2013

Safe iterator for List

Sometimes you want to write something like this:
foreach (var element in collection)
    if (SomeCondition(element)) collection.Remove(element);

This example will throw InvalidOperationException, as you cannot change the collection while iterating throught it with default iterator. Sure, you can transform this example into simple LINQ:
collection.RemoveAll(element => SomeCondition(element));

But there might be situations, when you would choose iterators. In this case you would need to implement the safe iterator - which allows you to change the collection during enumeration.

And this can be simply done:
public class MyList: List
{
    new public IEnumerator GetEnumerator()
    {
        List currentState = new List(this);
        foreach (T element in currentState)
            yield return element;
    }
}

[TestMethod()]
public void MyList_Test()
{
    MyList<int> list = new MyList<int>();
    list.Add(1);
    list.Add(2);

    foreach (int num in list)
        list.Add(num * 3);

    Assert.IsTrue(list.Count == 4);
    Assert.IsTrue(list[3] == 6);
}

As you can see - all you need to do is to change the GetEnumerator method, so it would enumerate the safe copy of your collection.