如果IQueryable<T>继承自IEnumerable<T>,那么为什么IQueryable<T>是LINQ to SQL?

4

IEnumerable<T> 表示 LINQ-to-object,而 IQueryable<T> 则是允许 LINQ-to-SQL 的接口。不过,IQueryable<T> 继承了 IEnumerable<T>,那么在数据库中如何使用 IQueryable<T> 进行行筛选,而在内存中则可以使用 IEnumerable<T> 进行对象筛选呢?


2
看看这篇文章是否有帮助:https://codeblog.jonskeet.uk/2011/02/20/reimplementing-linq-to-objects-part-43-out-of-process-queries-with-iqueryable/ - Jon Skeet
1
IQueryable<T> 注意,IQueryable<T> 并不保证是基于数据库的。实现 IQueryable<T> 接口的具体类会指定数据如何被检索,可以来自数据库、互联网、内存(.AsQueryable())等等。 - xanatos
请注意,Linq-toSQL是一个特定的(死胡同)产品。大多数IQueryables将由Entity Framework实现。 - H H
2个回答

8
你误解了继承和接口实现。 IQueryable<T> 继承了 IEnumerable<T>,但这与类之间的继承是完全不同的,派生类继承基类的实现。接口只是一种契约,它们背后没有实际的代码。
public interface IFoo
{
    void Foo(); //its simply a contract, no implementation at all.
}

public interface IBar: IFoo
{
    void Bar();
}

public class Foo: IFoo
{
    void Foo() { //Foo's sepecific implementation goes here }
}

public class Bar : IBar 
{
    void Foo() { //Bar's specific implementation goes here }
    void Bar() { //implementation goes here }
}
Bar 通过 IBar 实现 IFoo 并不意味着 FooBar 之间有任何关系。

第一行不是完全正确的。IQueryable和IEnumerable可以作为基类具有相同的效果。只是对于你的类图来说有些尴尬。 - H H
IQueryable<T>这个接口如何实现任何东西? - Rawling
显然,正确的措辞是继承。实现是提供方法的实际代码。 - Rawling
标准术语是实现一个接口,它只是一个契约而没有自己的代码。 - Mrinal Kamboj
一个类实现一个接口。一个接口继承另一个接口。 - Servy
显示剩余2条评论

3
他们并不一样,这是一个不准确的说法。
实际的实现代码位于扩展方法中,这些方法针对IEnumerable或IQueryable进行选择。
在EF中有一个
Where<T>(this IQueryable<T>, Expression<Predicate<T>> )

在System.Linq中有什么?
Where<T>(this IEnumerable<T>, Predicate<T>)

分辨率规则会优先选择IQueryable扩展而不是基本的Linq扩展,这种神奇的实现是通过Expression<>参数实现的。


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