如何有条件地删除一个.NET集合项 [英] How to conditionally remove items from a .NET collection

查看:135
本文介绍了如何有条件地删除一个.NET集合项的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图使用.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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆