请参阅与此问题重叠的What is the difference between IQueryable[T] and IEnumerable[T]?
IEnumerable<T>
代表了一个 T
的只向前游标。.NET 3.5 添加了扩展方法,其中包括 LINQ 标准查询操作符
,如 Where
和 First
,任何需要谓词或匿名函数的操作符都采用 Func<T>
。
IQueryable<T>
实现了相同的 LINQ 标准查询操作符,但接受 Expression<Func<T>>
作为谓词和匿名函数。 Expression<T>
是一个已编译的表达式树,是方法的分解版本(如果您愿意,可以说是“半编译的”),可由查询提供程序解析并相应地使用。
例如:
IEnumerable<Person> people = GetEnumerablePeople();
Person person = people.Where(x => x.Age > 18).FirstOrDefault();
IQueryable<Person> people = GetQueryablePeople();
Person person = people.Where(x => x.Age > 18).FirstOrDefault();
x => x.Age > 18
是一个匿名方法 (Func<Person, bool>
),可以像其他方法一样执行。 Enumerable.Where
将为每个人执行该方法,yield
返回方法返回 true
的值。x => x.Age > 18
是一个表达式树 (Expression<Func<Person, bool>>
),可以认为是“'Age' 属性是否大于 18”。IQueryable
(毕竟它实现了 IEnumerable<T>
),它可以组合多个查询运算符(在上面的示例中是 Where
和 FirstOrDefault
)以更智能的方式执行整个查询对基础数据源(如在 SQL 中使用 SELECT TOP 1
)。在现实生活中,如果您使用像LINQ-to-SQL这样的ORM
IQueryable
,则查询可能会转换为SQL并在数据库服务器上运行IEnumerable
,则在运行查询之前,所有行将作为对象加载到内存中。在这两种情况下,如果您不调用ToList()
或ToArray()
,则每次使用查询时都会执行查询,因此,假设您有一个IQueryable
,并从中填充4个列表框,则查询将针对数据库运行4次。
另外,如果您扩展查询:
q.Select(x.name = "a").ToList()
如果使用 IQueryable
,生成的SQL语句将包含 where name = "a"
,但如果使用 IEnumerable
,将从数据库中获取更多的内容,然后由 .NET 进行 x.name = "a"
的检查。
主要区别在于 IQueryable 定义的扩展方法接受 Expression 对象而不是 Func 对象,这意味着它接收的委托是一个表达式树而不是一个要调用的方法。IEnumerable 在处理内存集合方面非常出色,但 IQueryable 允许使用远程数据源,如数据库或 Web 服务。
来源:这里
IEnumerable IEnumerable适用于处理内存中的集合。 IEnumerable不会在项之间移动,它只能向前移动。
IQueryable IQueryable最适合远程数据源,比如数据库或Web服务。 IQueryable是一项非常强大的功能,支持多种有趣的延迟执行方案(例如分页和基于组合的查询)。
因此,当您需要简单地遍历内存中的集合时,请使用IEnumerable;如果您需要对集合进行任何操作,例如DataSet和其他数据源,请使用IQueryable。
主要区别在于IEnumerable会一直枚举它的所有元素,而IQueryable会根据查询枚举元素或执行其他操作。查询是一个表达式(.Net代码的数据表示),必须由IQueryProvider进行探索/解释/编译/其他以生成结果。
有一个查询表达式具有两个优点。
第一个优点是优化。因为类似“Where”的修饰符包含在查询表达式中,所以IQueryProvider可以应用否则无法进行的优化。而不是返回所有元素然后由于'Where'子句而扔掉大部分元素,提供程序可以使用哈希表来定位具有给定键的项。
第二个优点是灵活性。因为表达式是可探索的数据结构,所以您可以做像将查询序列化并将其发送到远程机器(例如linq-to-sql)这样的事情。
IQueryable与IEnumerable相同,但它还提供了额外的功能来使用Linq实现自定义查询。这是MSDN上的描述:http://msdn.microsoft.com/en-us/library/system.linq.iqueryable.aspx