为什么IQueryable缺少所有IQueryable<T>的扩展方法?

4

IEnumerableIEnumerable<T>类似。这是一个疏忽吗?或者当您没有指定类型时,是否存在问题,使得实现.Count().Where()等扩展功能不可能?

3个回答

4
文档中可以得知:
IQueryable接口是为查询提供程序实现而设计的。它只应该由同时实现了IQueryable<T>的提供程序来实现。如果提供程序没有同时实现IQueryable<T>,则标准查询运算符无法用于提供程序的数据源。
IEnumerable是.NET没有泛型时代的产物(当然我并不是说它已经被弃用了)。在引入泛型和IEnumerable<T>之后,为了向后兼容,它一直存在着。IQueryable保持了这种一致性。基本上,鉴于现在有了泛型,并且具有优势,将这些扩展仅实现在通用接口上变得有用。非泛型的接口总是可以使用Cast<T>转换为泛型接口。

1
不,这不是疏忽。大多数扩展 IQueryable<T>IEnumerable<T> 的方法需要知道项目的类型。显然,像 Count()Any() 这样的方法可以在非泛型接口上工作,但这可能会令人困惑。因此,适用于非泛型接口的唯一方法是使它们成为泛型接口(Cast<T>()OfType<T>())。

0

这可能是一个有意的决定而不是疏忽,因为可以使用Cast方法将IEnumerable\IQueryable始终转换为IEnumerable\IQueryable<object>

这会给调用者带来一些小的开销,但可以避免重复实现许多扩展,例如对于Where,您需要一个泛型和非泛型版本:

public static IEnumerable Where(this IEnumerable source, Func<object, bool> predicate) { ... }
public static IEnumerable<T> Where<T>(this IEnumerable<T> source, Func<T, bool> predicate) { ... }

1
这样做会有好处 - 您不必先调用 Cast<T> :) - MarcinJuraszek
2
@MarcinJuraszek - 这对用户来说是一个小好处,但额外的实现成本并不能证明这样一个小开销的合理性。 - Lee
2
不会的,因为IEnumerable<T>继承了IEnumerable方法,这些方法不需要直接类型知识(例如Count()Any()),可以在IEnumerable上实现,而其余的方法(例如Where(pred)Select(func)等)则在IEnumerable<T>上实现。 - MarcinJuraszek
@MarcinJuraszek - 可能适用于 Count,但大多数 Linq 扩展都可以在 IEnumerable 上实现,对于这些扩展,您必须实现两次。 - Lee
1
@BlueRaja-DannyPflughoeft - 有人必须实现它们,而对于他们来说,这样做是有成本的。问题是IEnumerable上缺少Linq扩展是否是一个疏忽。我认为这可能是故意的,因为为IEnumerable\IQueryable的非泛型版本再次实现大多数方法并没有显著的好处。 - Lee
显示剩余3条评论

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