如何有条件地删除一个.NET集合项 [英] How to conditionally remove items from a .NET collection
问题描述
我试图使用.NET编写的扩展方法,将运行在一个通用的集合,从集合中删除匹配给定条件的所有项目。
I'm trying to write an extension method in .NET that will operate on a generic collection, and remove all items from the collection that match a given criteria.
这是我第一次尝试:
public static void RemoveWhere<T>(this ICollection<T> Coll, Func<T, bool> Criteria){
foreach (T obj in Coll.Where(Criteria))
Coll.Remove(obj);
}
然而,这引发InvalidOperationException集合已修改;枚举操作可能不会执行。这有一定道理,所以我做了第二次尝试与第二个集合变量来保存需要被删除,遍历,与其相关的项目:
However this throws an InvalidOperationException, "Collection was modified; enumeration operation may not execute". Which does make sense, so I made a second attempt with a second collection variable to hold the items that need to be removed and iterate through that instead:
public static void RemoveWhere<T>(this ICollection<T> Coll, Func<T, bool> Criteria){
List<T> forRemoval = Coll.Where(Criteria).ToList();
foreach (T obj in forRemoval)
Coll.Remove(obj);
}
这将引发相同的异常;我不知道我真正明白,为什么是'科尔'不再被遍历集合,所以为什么不能修改?
This throws the same exception; I'm not sure I really understand why as 'Coll' is no longer the collection being iterated over, so why can't it be modified?
如果任何人有任何建议,我怎么能得到这个工作,或者更好的方法来达到同样的,那简直太好了。
If anyone has any suggestions as to how I can get this to work, or a better way to achieve the same, that'd be great.
感谢。
推荐答案
有关名单,其中,T&GT;
,这个已经存在,如 removeall过(predicate&LT; T&GT;)
。因此,我建议您将该名称(允许熟悉,和precedence)。
For List<T>
, this exists already, as RemoveAll(Predicate<T>)
. As such, I'd suggest that you keep the name (allowing familiarity, and precedence).
基本上,你不能删除,而迭代。有两个常用的选项:
Basically, you can't remove while iterating. There are two common options:
- 使用索引器基于迭代(
为
)和去除 - 缓冲物品取出,之后删除
的foreach
(因为你已经做了)
- use indexer based iteration (
for
) and removal - buffer the items to remove, and remove after the
foreach
(as you've already done)
所以,现在可能:
public static void RemoveAll<T>(this IList<T> list, Func<T, bool> predicate) {
for (int i = 0; i < list.Count; i++) {
if (predicate(list[i])) {
list.RemoveAt(i--);
}
}
}
或者更普遍的任何的ICollection&LT; T&GT;
:
public static void RemoveAll<T>(this ICollection<T> collection, Func<T, bool> predicate) {
T element;
for (int i = 0; i < collection.Count; i++) {
element = collection.ElementAt(i);
if (predicate(element)) {
collection.Remove(element);
i--;
}
}
}
该方法具有避免大量列表的额外副本的优势。
This approach has the advantage of avoiding lots of extra copies of the list.
这篇关于如何有条件地删除一个.NET集合项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!