c# - 如何有条件地从 .NET 集合中删除项目

标签 c# .net collections extension-methods

我正在尝试在 .NET 中编写一个扩展方法,它将对通用集合进行操作,并从集合中删除符合给定条件的所有项目。

这是我的第一次尝试:

public static void RemoveWhere<T>(this ICollection<T> Coll, Func<T, bool> Criteria){
    foreach (T obj in Coll.Where(Criteria))
        Coll.Remove(obj);
}

然而,这将引发 InvalidOperationException,“集合已修改;枚举操作可能无法执行”。这确实有道理,所以我第二次尝试使用第二个集合变量来保存需要删除的项目并迭代它:

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

这会抛出同样的异常;我不确定我是否真的理解为什么“Coll”不再是正在迭代的集合,所以为什么不能修改它?

如果有人对我如何实现它有任何建议,或者有更好的方法来实现同样的效果,那就太好了。

谢谢。

最佳答案

对于 List<T> ,这已经存在,如RemoveAll(Predicate<T>) .因此,我建议您保留名称(允许熟悉和优先)。

基本上,您不能在迭代时删除。有两个常见的选项:

  • 使用基于索引器的迭代(for)和移除
  • 缓冲要删除的项目,并在foreach之后删除(就像你已经做过的那样)

也许:

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<T> :

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

这种方法的优点是避免了列表的大量额外副本。

关于c# - 如何有条件地从 .NET 集合中删除项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/653596/

相关文章:

c# - 如何在 Visual Studio 中使用 "Light bulb"重构工具来使用显式类型而不是 var?

c# - 如何在一个查询中获取具有角色的用户?

c# - SessionID 抛出 null 异常

c# - 在哪里存储将在我的应用程序中使用的常量对象

c# - System.Collections 与 System.Collections.ObjectModel

java - 具有独特元素的有序集合并替换最旧的元素

c# - 如何在 Jetbrains Rider 中自动重新排列代码?

c# - WPF 工具提示不更新

.net - TeamCity WCF RIA 在构建期间缺少程序集

java - 迭代 CopyOnWriteArrayList 时出现 UnsupportedOperationException