C# 为什么IEnumerable没有FindAll或RemoveAll方法?
在我看来,IList上的许多扩展方法都同样适用于IEnumerable,比如FindAll和RemoveAll 有人能解释它们不存在的原因吗?RemoveAll毫无意义,因为该API上没有Remove etc-但是从3.5开始就有FindAll-但它被称为Where: 这相当于:C# 为什么IEnumerable没有FindAll或RemoveAll方法?,c#,linq,collections,extension-methods,ienumerable,C#,Linq,Collections,Extension Methods,Ienumerable,在我看来,IList上的许多扩展方法都同样适用于IEnumerable,比如FindAll和RemoveAll 有人能解释它们不存在的原因吗?RemoveAll毫无意义,因为该API上没有Remove etc-但是从3.5开始就有FindAll-但它被称为Where: 这相当于: IEnumerable<Foo> source = ... var filtered = from x in source where x.IsActive &&
IEnumerable<Foo> source = ...
var filtered = from x in source
where x.IsActive && x.Id == 25
select x;
For RemoveAll不适用于IEnumerable,因为IEnumerable是只读的。
对于FindAll,请参见Marc的答案。IEnumerable所做的就是指定有一个可以枚举或迭代的集合。它甚至没有指定集合可以多次迭代,更不用说操作了。因此,任何操纵集合的方法都没有意义。然而,像FindAll这样的方法是有意义的。Enumerable并不意味着存在一个底层集合,因此您无法知道是否有要从中删除的内容。如果存在基础集合,则不知道它是否支持删除操作 下面是一个枚举奇数的示例方法。如果您可以从enumerable中删除7,会发生什么?它将从何处移除
public IEnumerable<int> GetOddPositiveNumbers()
{
int i = 0;
while (true)
{
yield return 2*(i++)+1;
}
}
您可能要查找的是允许您筛选可枚举项的位置和例外情况。公平地说,如果您实际需要的是特定集合的零长度版本,则类似IEnumerable.RemoveAll的内容实际上是有意义的。调用它RemoveAll没有意义,因为IEnumerable方法实现不应该修改集合
所以在我的例子中,我有时使用一个自定义扩展方法,我称之为Nil
至于Marc已经指出的FindAll,简称为Where。感谢您的解释,我现在看到了更多的图片,但我可以接着问两个相关的问题吗:1为什么List实现FindAll以及Where,假设它们是相同的:2为什么ICollection不实现RemoveAll,因为它实现Remove?谢谢Andy@Andy我不认为这有什么原因,但你可以自己写一个扩展方法,看看我的答案。@Andy List得到一个Where,因为它实现了IEnumerable。Re-ICollection:因为向接口添加额外的方法不是一个好主意,但是,在接口上使用扩展方法实现它是完全可能的,感谢这些回复。我认为另一件让我困惑的事情是IEnumerable确实有一个remove方法,但仔细检查它确实有作用different@MarcGravell:关于ICollection,向现有接口添加方法可能不切实际,但是,作为标准集合接口的一部分,RemoveAll比Find或Remove更合理[任何为IsReadOnly返回false的集合都应该能够实现它,没有它就无法实现等效功能]。在可枚举的上下文中,“Remove”只表示不在其上枚举。
public IEnumerable<int> GetOddPositiveNumbers()
{
int i = 0;
while (true)
{
yield return 2*(i++)+1;
}
}
static IEnumerable<T> Nil<T>(this IEnumerable<T> self) {
yield break;
}