您可以从列表<>删除一个项目,同时通过在C#迭代(Can you remove an i

2019-07-21 15:42发布

您可以从列表中<>,同时通过它遍历删除一个项目? 将这项工作,还是有更好的方式来做到这一点?

我的代码:

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

CNC中对不起球员,这是一个Silverlight游戏。 我没有意识到的Silverlight是对Compact Framework的不同。

Answer 1:

编辑 :澄清,这个问题是关于Silverlight的 ,这显然不支持removeall过上List`T 。 它可以在完整的框架,CF,XNA版本2.0+

您可以编写表达你去除标准拉姆达:

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);
    }
}


Answer 2:

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

编辑:为了使这项工作,是在Silverlight中,下面的扩展方法添加到您的项目。

List<T>.RemoveAll ,这种算法是O(N),其中N是该列表的长度,而不是O(N * M),其中M是从列表中删除的元素的数量。 因为它是一个扩展方法具有相同的原型为RemoveAll非Silverlight的框架中发现的方法,内置的一个将被使用时可用,而这一次的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;
    }
}


Answer 3:

试图foreach循环中删除它会抛出异常。 你需要通过它向后兼容for循环迭代。

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


Answer 4:

试试这个:

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


Answer 5:

这是更好地要么创建包含项目删除,然后从列表中删除项目的列表:

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);
}


Answer 6:

在迭代“for”循环而不是通过迭代的foreach。 这将工作。



Answer 7:

我已经遇到这个问题之前,这里的博客上讲述它 。

短版是你可以创建一个名为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(); });


文章来源: Can you remove an item from a List<> whilst iterating through it in C#