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


我试图了解IQueryable,ICollection,IList和IDictionary接口之间的区别 这对于迭代,索引,查询等基本操作来说更快。

像Collection,List,Dictionary等类这样的类可以很好地启动这些接口,什么时候应该使用这些类。使用这些类比其他类的基本优势。

我尝试阅读其他类似问题的帖子,但没有回答我的完整问题。 谢谢您的帮助。


42
2017-12-15 22:06


起源




答案:


所有这些接口都继承自 IEnumerable的,你应该确保你理解。该接口基本上允许您在a中使用该类 foreach 声明(在C#中)。

  • ICollection的 是您列出的最基本的接口。它是一个可枚举的接口,支持Count,就是它。
  • IList的 是ICollection的一切,但它也支持添加和删除项目,通过索引检索项目等。它是“对象列表”最常用的界面,我知道这是模糊的。
  • IQueryable的 是一个支持LINQ的可枚举接口。您始终可以从IList创建IQueryable并使用LINQ to Objects,但您也可以在LINQ to SQL和LINQ to Entities中找到用于延迟执行SQL语句的IQueryable。
  • IDictionary的 在某种意义上它是一种不同的动物,它是唯一键到值的映射。它也是可枚举的,因为您可以枚举键/值对,但除此之外它与您列出的其他目的不同。

每个MSDN文档都是不错的,所以我会从那里开始理解你的理解。


97
2017-12-15 22:14



+1这些接口的详细解释,但你错过了我的其他问题 - Praneeth
就接口的通用版本而言,ICollection <T>支持Add / Remove / Clear / Contains / CopyTo msdn.microsoft.com/en-us/library/92t2ye13.aspx - Joshua Rodgers


IQueryable,IList,IDictionary,ICollection继承IEnumerable接口。 类型集合的所有接口都将继承IEnumerable接口。

IEnumerable和IQueryable之间的差异 IEnumerable的: - 当您运行的返回IEnumerable类型的查询时。 IEnumerable将首先执行第一个查询,然后执行为该查询编写的子查询。

: - 如果你想获得特定国家的前10个人口记录,那么我们将在LinQ中使用的查询是

IEnumerable _Population =来自印度的s选择s.population; // First Query _Population = _Population.take(10); //第二次查询

现在,如果我们执行此查询,将首先执行First Query,IEnumerable将从sql server获取所有填充的记录,然后它将数据存储在In Process内存中,然后它将在下一个Query中执行前10个填充。 (在sql server上执行两次)。

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

IQueryable _Population =来自印度的s选择s.population; // First Query _Population = _Population.take(10); //第二次查询

在这个IQueryable中,它将同时执行两个查询,因为它将获得单个查询中前10名的填充,而不是获取数据并再次过滤前10个。(在sql server上执行一次) 。

IQueryable和IEnumerable的结论

  1. 如果您正在针对数据库中的数据编写查询,那么 使用IQueryable。
  2. 如果您正在查询进程中的数据 使用IEnumerable。 IEnumerable有一个方法GetEnumerator(),Current()和MoveNext()。

4
2018-03-23 11:51



真的很高兴知道差异。 (y)的 - Wasim Bajwa
扩展方法 Take 定义于 IEnumerable<T> 代替。我证实了这一点 只有1个 在两种情况下都会触发查询 IEnumerable 要么 IQueryable。就是这样 IEnumerable 内存中过滤会通过线路带来不需要的数据。 - RBT


我注意到上面@ gunny229的答案中有几个问题,这就是我写这篇文章的原因。我也在他的帖子的评论区域提到了这些问题。为了纠正这个帖子,我不得不重写几乎所有的帖子,所以我想创建自己的帖子。我不打算完整地讨论OP的问题,但我想指出 使用LINQ to SQL时IQueryable和IEnumerable之间的区别

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

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

这是记录插入脚本(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

现在我的目标是简单地从前2个记录 Employee 数据库中的表。所以,我在指向的控制台应用程序中添加了一个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 profiler会话,这里是执行摘要:

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

就是这样 IQueryable 很聪明,适用于 Top (2) 数据库服务器端本身的子句因此它通过网络只带来5条记录中的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 带来了所有5条记录 Salary 表然后在客户端计算机上执行内存中过滤以获得前2个记录。因此,更多数据(在这种情况下为3个附加记录)不必要地通过线路传输。


2
2018-04-26 02:26