您可以从列表<>中删除项目吗?在C#中迭代它

时间:2009-10-09 04:24:58

标签: c# .net silverlight list iteration

您可以从列表<>中删除项目吗?在迭代它的同时?这会有用,还是有更好的方法呢?

我的代码:

foreach (var bullet in bullets)
  {
    if (bullet.Offscreen())
    {
      bullets.Remove(bullet);
    }
  }

-edit-对不起,伙计们,这是一个银色的游戏。我没有意识到Silverlight与Compact Framework不同。

7 个答案:

答案 0 :(得分:17)

bullets.RemoveAll(bullet => bullet.Offscreen());

修改:要在Silverlight中按原样运行此工作,请将以下扩展方法添加到项目中。

List<T>.RemoveAll类似,此算法为O(N),其中N是列表的长度,而不是O(N * M),其中M是从列表中删除的元素数。因为它是一个扩展方法,与非Silverlight框架中的RemoveAll方法具有相同的原型,所以内置的一个将在可用时使用,并且这个无缝地用于silverlight构建。

public static class ListExtensions
{
    public static int RemoveAll<T>(this List<T> list, Predicate<T> match)
    {
        if (list == null)
            throw new NullReferenceException();

        if (match == null)
            throw new ArgumentNullException("match");

        int i = 0;
        int j = 0;

        for (i = 0; i < list.Count; i++)
        {
            if (!match(list[i]))
            {
                if (i != j)
                    list[j] = list[i];

                j++;
            }
        }

        int removed = i - j;
        if (removed > 0)
            list.RemoveRange(list.Count - removed, removed);

        return removed;
    }
}

答案 1 :(得分:10)

修改:澄清一下,问题是 Silverlight ,显然不支持RemoveAll on List`T。它可以在full framework, CF, XNA versions 2.0+

中找到

您可以编写一个表达删除条件的lambda:

bullets.RemoveAll(bullet => bullet.Offscreen());

或者您可以选择您想要的那些,而不是删除您不想要的那些:

bullets = bullets.Where(b => !b.OffScreen()).ToList();

或使用索引器向后移动序列:

for(int i=bullets.Count-1;i>=0;i--)
{
    if(bullets[i].OffScreen())
    {
        bullets.RemoveAt(i);
    }
}

答案 2 :(得分:4)

尝试在foreach循环中删除它会引发异常。你需要使用for循环向后迭代它。

for (int count = bullets.Count - 1; count >= 0; count--)
{
  if (bullets[count].Offscreen())
    {
        //bullets.Remove(bullets[count]);
        bullets.RemoveAt(count);
    }
}

答案 3 :(得分:3)

试试这个:

bullets.RemoveAll(bullet => bullet.Offscreen());

答案 4 :(得分:2)

最好创建一个包含要删除的项目的列表,然后从列表中删除项目:

List<Bullet> removedBullets = new List<Bullet>();

foreach(var bullet in bullets)
{
  if (bullet.OffScreen())
  {
   removedBullets.Add(bullet);
  }
}

foreach(var bullet in removedBullets)
{
  bullets.Remove(bullet);
}

答案 5 :(得分:2)

迭代“for”循环而不是迭代foreach。这将有效。

答案 6 :(得分:1)

I've come across this problem before and blogged about it here

简短版本是您可以创建名为RemoveIf的扩展方法:

public void RemoveIf<T>(ICollection<T> collection, Predicate<T> match)
{
    List<T> removed = new List<T>();
    foreach (T item in collection)
    {
        if (match(item))
        {
            removed.Add(item); 
        }
    }

    foreach (T item in removed)
    {
        collection.Remove(item);
    }

    removed.Clear();
}

然后只需在每次需要时与您的代表联系:

RemoveIf(_Entities.Item, delegate(Item i) { return i.OffScreen(); });