为啥 Enumerable 不继承自 IEnumerable<T>
Posted
技术标签:
【中文标题】为啥 Enumerable 不继承自 IEnumerable<T>【英文标题】:Why Enumerable doesn't inherits from IEnumerable<T>为什么 Enumerable 不继承自 IEnumerable<T> 【发布时间】:2011-03-01 13:35:47 【问题描述】:我对这个问题很困惑,无法理解。在Enumerable
文档中,我读到了这个:
实现 System.Collections.Generic.IEnumerable
还有一些像Select()
这样的方法返回IEnumerable<TSource>
,我们可以在使用它之后从像Where()
这样的其他方法中使用它们。例如:
names.Select(name => name).Where(name => name.Length > 3 );
但Enumerable
不继承自IEnumerable<T>
和IEnumerable<T>
也不包含Select()
、Where()
等...
我错了吗? 还是有什么原因?
【问题讨论】:
【参考方案1】:Select()、Where() 等是“extension methods”。它们需要在“其他地方”定义,因为接口不能提供方法的实现。
您可以通过参数列表中的关键字“this”来识别扩展方法。例如:
public static IEnumerable<TSource> Where<TSource>(
this IEnumerable<TSource> source,
Func<TSource, bool> predicate
)
可以像使用 IEnumerable<TSource>
上的方法一样使用,带有一个参数:Func<TSource, bool> predicate
。
【讨论】:
【参考方案2】:正确。但是这句话呢?
实现 System.Collections.Generic.IEnumerable
按照这句话,我们要在IEnumerable<T>
接口中定义方法,通过继承在Enumerable
类中实现。对吗?
为什么首选扩展方法而不是继承?
【讨论】:
请注意,您应该添加评论或编辑您的问题,而不是创建新答案来添加新信息或问题。【参考方案3】:IEnumerable 出现在IEnumerable<T>
之前,这是一个 2.0+ 接口。
【讨论】:
【参考方案4】:“为什么首选扩展方法而不是继承?”
Enumerable 是一个静态类,它为 IEnumerable 实现了 50 多种扩展方法。这使您可以在实现 IEnumerable 的类型上使用所有这些扩展方法,而无需强制程序员为每个集合类型实现所有这些方法。如果 Enumerable 是一个接口而不是一个静态类,那么每个集合类型(例如 List、Dictionary、Set 等)都会有自己的这些扩展方法的实现。
【讨论】:
【参考方案5】:解决此问题的一种方法是使用Cast<T>()
方法将元素转换为相同的类型,该方法返回相同元素的IEnumerable<T>
版本。
DataTable dt = ...
dt.Rows.Cast<DataRow>().Where()...
Rows
是 IEnumerable
类型,转换后它变成 IEnumerable<DataRow>
类型,这是 LINQ 扩展方法支持的。
【讨论】:
【参考方案6】:我曾说过,您还阅读了 Jon Skeet 撰写的这篇文章 Iterators, iterator blocks and data pipelines 以获得更多见解
【讨论】:
这是关于扩展方法,而不是迭代器块以上是关于为啥 Enumerable 不继承自 IEnumerable<T>的主要内容,如果未能解决你的问题,请参考以下文章
为啥 Enumerable 不实现 IEnumerable?
为啥不推荐使用 Enumerable#each_with_object ?
为啥 Enumerable 中的方法返回 Enumerator?