你可以在C#中迭代它时从List 中删除一个项目吗?
您可以在迭代它时从列表中删除项目吗? 这会有用,还是有更好的方法呢?
我的代码:
foreach (var bullet in bullets) { if (bullet.Offscreen()) { bullets.Remove(bullet); } }
-edit-对不起,伙计们,这是一个silverlight的游戏。 我没有意识到Silverlight与Compact Framework不同。
编辑 :澄清一下,问题是关于Silverlight ,它显然不支持List`T上的RemoveAll 。 它在完整的框架,CF,XNA版本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); } }
bullets.RemoveAll(bullet => bullet.Offscreen());
编辑:要使此工作在Silverlight中按原样运行,请将以下扩展方法添加到项目中。
与List
,此算法为O(N),其中N是列表的长度,而不是O(N * M),其中M是从列表中删除的元素的数量。 因为它是一个扩展方法,与非Silverlight框架中的RemoveAll
方法具有相同的原型,所以内置的一个将在可用时使用,并且这个无缝地用于silverlight构建。
public static class ListExtensions { public static int RemoveAll(this List list, Predicate 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; } }
试图在foreach循环中删除它会引发exception。 您需要使用for循环向后迭代它。
for (int count = bullets.Count - 1; count >= 0; count--) { if (bullets[count].Offscreen()) { //bullets.Remove(bullets[count]); bullets.RemoveAt(count); } }
试试这个:
bullets.RemoveAll(bullet => bullet.Offscreen());
最好是创建一个包含要删除的项目的列表,然后从列表中删除项目:
List removedBullets = new List (); foreach(var bullet in bullets) { if (bullet.OffScreen()) { removedBullets.Add(bullet); } } foreach(var bullet in removedBullets) { bullets.Remove(bullet); }
迭代“for”循环而不是迭代foreach。 这会奏效。
我以前遇到过这个问题,并在这里写博客 。
简短版本是你可以创建一个名为RemoveIf的扩展方法:
public void RemoveIf(ICollection collection, Predicate match) { List removed = new List (); 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(); });