IQueryable,ICollection,IList和IDictionary接口之间的区别

我正在尝试理解IQueryable,ICollection,IList和IDictionary接口之间的区别,它对于迭代,索引,查询等基本操作更为快捷。

像集合,列表,词典等类,将是很好的启动这些接口,我们应该什么时候使用这些类。 使用这些类相对于其他类的基本优势。

我尝试阅读其他类似问题的post,但没有回答我的全部问题。 谢谢您的帮助。

所有这些接口inheritanceIEnumerable ,你应该确保你明白。 该接口基本上可以让你在foreach语句中使用该类(在C#中)。

  • ICollection是您列出的接口中最基本的。 这是一个支持计数的枚举接口,就是这个。
  • IList是ICollection的一切,但它也支持添加和删除项目,通过索引检索项目等。这是“对象列表”最常用的接口,这是我知道的模糊。
  • IQueryable是一个支持LINQ的枚举接口。 您总是可以从IList创build一个IQueryable并使用LINQ to Objects,但是您也会发现IQueryable用于延迟执行LINQ to SQL和LINQ to Entities中的SQL语句。
  • IDictionary是一种不同的动物,它是唯一键值映射。 这也是可枚举的,你可以枚举键/值对,但除此之外,它的作用与您列出的其他目的不同。

每个MSDN文档都很体面,所以我会从这里开始理解你的理解。

IQueryable,IList,IDictionary,ICollectioninheritanceIEnumerable接口。 所有types集合的接口都将inheritanceIEnumerable接口。

IEnumerable和IQueryable IEnumerable 之间的区别 : – 当你运行一个IEnumerabletypes的查询时。 IEnumerable将首先执行第一个查询,然后执行为该查询编写的子查询。

例如 : – 如果你想得到一个特定国家的前10名人口logging,那么我们将在LinQ中使用的查询是

IEnumerable _Population = from s在印度selects.population; //第一个查询_Population = _Population.take(10); //第二个查询

现在,如果我们执行这个查询,首先执行第一个查询,IEnumerable将从SQL Server获取所有人口的logging,然后将数据存储在进程内存中,然后在下一个查询中执行前10个人口。 (执行发生在SQL服务器上两次)。

如果我们使用IQueryable执行相同的查询。

IQueryable _Population = from s在印度selects.population; //第一个查询_Population = _Population.take(10); //第二个查询

在这个IQueryable中,它将同时执行两个查询,它将在单个查询中获得排名前10的人口,而不是获取数据并再次过滤前10个数据(在SQL Server上执行一次) 。

IQueryable和IEnumerable的结论

  1. 如果您正在对数据库中的数据编写查询,请使用IQueryable。
  2. 如果您正在查询正在处理的数据,则使用IEnumerable。 IEnumerable有一个方法GetEnumerator(),Current()和MoveNext()。

我注意到在@ gunny229的答案上面的几个问题,这就是为什么我写这篇文章。 我在他的post的评论区也提到了这些问题。 要纠正这个post,我将不得不重写几乎整个职位,所以我想创build自己的。 我不打算全面地讨论OP的问题,但是我想在使用LINQ to SQL时指出IQueryable和IEnumerable之间区别

我在DB(DDL脚本)中创build了以下结构:

 CREATE TABLE [dbo].[Employee]([PersonId] [int] NOT NULL PRIMARY KEY,[Salary] [int] NOT NULL) 

这里是logging插入脚本(DML脚本):

 INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(1, 20) INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(2, 30) INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(3, 40) INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(4, 50) INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(5, 60) GO 

现在我的目标是简单地从数据库中的Employee表中获取前两个logging。 所以,我添加了一个ADO.NET实体数据模型项到我的控制台应用程序中,指向我的数据库中的Employee表,并开始编写LINQ查询。

IQueryable路由的代码

 using (var efContext = new EfTestEntities()) { IQueryable<int> employees = from e in efContext.Employees select e.Salary; employees = employees.Take(2); foreach (var item in employees) { Console.WriteLine(item); } } 

当我开始运行这个程序时,我还在SQL Server实例上启动了一个SQL Query分析器会话,这里是执行摘要:

  1. 查询总数: 1
  2. 查询文本: SELECT TOP (2) [c].[Salary] AS [Salary] FROM [dbo].[Employee] AS [c]

只是IQueryable足够聪明,可以在数据库服务器端自身应用Top (2)子句,因此它只能通过线路传输5个logging中的2个。 客户端计算机上不需要任何进一步的内存过滤。

IEnumerable路由代码

 using (var efContext = new EfTestEntities()) { IEnumerable<int> employees = from e in efContext.Employees select e.Salary; employees = employees.Take(2); foreach (var item in employees) { Console.WriteLine(item); } } 

在这种情况下的执行摘要:

  1. 查询总数: 1
  2. 查询在SQL事件探查器中捕获的文本: SELECT [Extent1].[Salary] AS [Salary] FROM [dbo].[Employee] AS [Extent1]

现在的事情是IEnumerable带来了Salary表中的所有5条logging,然后在客户端计算机上执行了内存过滤,以获得前2条logging。 所以更多的数据(在这种情况下是3个额外的logging)不必要的通过电线传输。