如何在IEnumerable<MyClass>中移除元素?

3

如何从IEnumerable中删除符合特定条件的项目?

RemoveAll()不适用。


你有类的定义和要求吗? - Mike Schwartz
可能是从IEnumerable<T>中删除项的重复问题。 - Ahmet Kakıcı
9个回答

12

你不能;IEnumerable作为一个接口不支持移除操作。

如果你的 IEnumerable 实例实际上是一个支持移除操作的类型(例如 List<T>),那么你可以将其强制转换为该类型,并使用 Remove 方法。

或者,你可以根据自己的条件将项目复制到另一个基于 IEnumerable 的集合中,也可以使用延迟评估查询(例如 Linq 的 .Where)动态筛选你的 IEnumerable 。但这两种方法都不会影响你的原始容器。


在我的情况下,代码正在IEnumerable上执行.Aggregate。我按照丹的建议插入了一个.Where过滤器,例如foo.Where(condition).Aggregate(expression)。它非常顺利地工作了。 - Codes with Hammer

3
这将生成一个新的集合,而不是修改现有的集合。然而,我认为使用LINQ进行操作是惯用的方式。
    var filtered = myCollection.Where(x => x.SomeProp != SomValue);

另一个选择是使用Where创建一个新的IEnumerable<T>,其中包含对要删除的对象的引用,然后将其传递给原始集合上的Remove调用。当然,这实际上会消耗更多的资源。


在“这将产生一个新的集合”中,“this”是什么? - Austin Salonen
@AustinSalonen 使用 Where 将会产生一个新的集合。LINQ 查询通常不会修改现有的集合,而是生成一个带有结果集的新的 IEnumerable<T> - evanmcdonnal

1

正如大家已经说过的那样,您不能从IEnumerable中删除元素,因为这不是该接口所描述的。考虑以下示例:

public IEnumerable<string> GetSomeStrings()
{
    yield return "FirstString";
    yield return "Another string";
}

显然,从这个 IEnumerable 中删除一个元素并不是你可以合理地做的事情,相反,你需要创建一个新的枚举,不包含你不想要的元素。

yield 关键字提供了其他示例,例如,你可以拥有无限列表:

public IEnumberable<int> GetPowersOf2()
{
    int value = 1;
    while(true)
    {
        yield return value;
        value = value * 2;
    }
}

1
你无法从 IEnumerable<T> 中移除项目。你可以从 ICollection<T> 中移除项,或者从 IEnumerable<T> 中过滤项目。
// filtering example; does not modify oldEnumerable itself
var filteredEnumerable = oldEnumerable.Where(...);
// removing example
var coll = (ICollection<MyClass>)oldEnumerable;
coll.Remove(item);

1
您不能从IEnumerable中删除项目。这是不可能的。它只是一系列项目。您可以从生成序列的某些基础源中删除项目,例如,如果IEnumerable基于列表,则可以从该列表中删除项目。
您的另一个选择是创建一个新序列,基于此序列,该序列永远不显示给定的项目。您可以使用Where来实现这一点,但重要的是要意识到这不是删除项目,而是根据某种条件选择显示项目。

这并非不可能。@TimS. 在他的回答中提到了它。另外请参考我在另一个关于类似主题的问题上的回答,网址为https://dev59.com/FmUo5IYBdhLWcg3wzCBq#15858794。 - Steve
@Steve,正如我在答案中所述,您可以从某个集合中删除项,该集合是IEnumerable的基础数据源。但这仍然不是从IEnumerable中删除项,而是从基础数据源中删除项。 - Servy
1
你说得对 - 我没有仔细地阅读你的答案 :) - Steve

0

这是我的做法,

IEnumerable<T> myVar=getSomeData(); // Assume mayVar holds some data

myVar=myVar.Where(d=>d.Id>10); // thats all, i want data with Id>10 only

0

无法从 IEnumerable<T> 中移除项目。来自 文档

公开枚举器,该枚举器支持对指定类型的集合进行简单迭代。


0
你可以将其转换并使用List<T>.RemoveAll(Predicate<T> match),这正是你所需要的。

-1

尝试使用Enumerable.Empty怎么样?

T obj = new T();
IEnumerable<T> myVar = new T[]{obj}    //Now myVar has an element
myVar = Enumerable.Empty<T>();        //Now myVar is empty

1
给变量赋一个新的值不会影响原来的值。 - Servy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接