Search code examples
c#listxna-4.0

C# List<t>.ForEach(delegate(type t) and how to remove items as the list is iterated through


This may be considered bad programming, but prior to .net 4, I used to heavily use code similar to this:

    enemyList.ForEach(delegate(Enemy e)
    {
        e.Update();
        if (someCondition)
              enemyList.Remove(e);
    });

Now, I'm going through an updating some old projects, and there are a LOT of code thats going to have to be changed since ForEach was removed.. Now, I do have an extension to allow me to use the ForEach :

    public static void ForEach<T>(this IEnumerable<T> sequence, Action<T> action)
    {
        if (sequence == null) throw new ArgumentNullException("sequence");
        if (action == null) throw new ArgumentNullException("action");
        foreach (T item in sequence)
            action(item);
    }

I know I can do this:

    var index = 0;
    while(index < enemyList.Count)
    {
        if(condition)
            enemyList.RemoveAt(index);
        else
            index++;
    }

But some of those would be a pain to rewrite like that.. Is there any way to add that functionality back so that I can iterate through that list, remove the items I need without having to go back and rewrite and edit all of those functions ? I still consider myself a newbie to coding, and I just can't figure this one out.. Any help would be appreciated!

********* EDIT *********

So I guess it boils down to rewriting a lot of code.. I have a lot of code such as this that I just pulled out of a project:

            GameplayScreen.gameWorld.shipList.ForEach(delegate(Ship s)
            {
                if (eS.originalShipsID == s.shipID)
                {
                    if (!eS.Alive || eS.health <= 0)
                    {
                        // this one sunk...
                        string log = "0" + s.shipName + " was sunk in battle.. All crew and cargo were lost.";
                        AddLogEntry(log);
                        totalCrewLost += s.currentCrew;
                        GameplayScreen.gameWorld.shipList.Remove(s);
                    }
                }
            });

I was just hoping there was a way to not have to rewrite all of that.. So time to update and change the way I code apparently. Thanks!


Solution

  • Use the list's RemoveAll method.

    You can refactor the code to:

    enemyList.RemoveAll(enemy => enemy.SomeCondition);
    

    Not only is it better than the while loop, I'd argue it's quite a bit better than the Foreach method.