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

Posted

技术标签:

【中文标题】IQueryable、ICollection、IList 和 IDictionary 接口之间的区别【英文标题】:Difference between IQueryable, ICollection, IList & IDictionary interface 【发布时间】:2011-05-26 05:18:11 【问题描述】:

我想了解 这对于迭代、索引、查询等基本操作更快。

Collection、List、Dictionary 等哪个类适合使用这些接口进行初始化,以及我们应该何时使用这些类。与其他类相比,使用这些类的基本优势。

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

【问题讨论】:

【参考方案1】:

所有这些接口都继承自 IEnumerable,您应该确保自己理解这一点。该接口基本上允许您在 foreach 语句中使用该类(在 C# 中)。

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

每一个的 MSDN 文档都很不错,所以我将从那里开始完善您的理解。

【讨论】:

+1 获取这些接口的详细说明,但您错过了我的其他问题 在接口的通用版本方面,ICollection 支持 Add/Remove/Clear/Contains/CopyTo,按照msdn.microsoft.com/en-us/library/92t2ye13.aspx【参考方案2】:

我注意到上面@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

现在我的目标是简单地从数据库中的 Employee 表中获取前 2 条记录。因此,我在控制台应用程序中添加了一个 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 查询分析器会话,这里是执行摘要:

    触发的查询总数:1 查询文本: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 在 SQL 分析器中捕获的查询文本:SELECT [Extent1].[Salary] AS [Salary] FROM [dbo].[Employee] AS [Extent1]

现在问题是IEnumerable 带来了Salary 表中存在的所有 5 条记录,然后在客户端计算机上执行内存过滤以获得前 2 条记录。因此,更多数据(在本例中为 3 条额外记录)不必要地通过网络传输。

【讨论】:

谢谢,但我不认为@gunny229 的回答具有误导性。是的,他使用了“查询”这个词,但这不是在数据库的上下文中。获得前两个只是另一个计算。至少我在阅读时是这样认为的。干杯。【参考方案3】:

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

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

示例:-如果您想获得来自特定国家/地区的前 10 名人口记录,那么我们将在 LinQ 中使用的查询是

IEnumerable _Population=from s in India select s.population;//第一次查询 _Population=_Population.take(10);//第二次查询

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

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

IQueryable _Population=from s in India select s.population;//第一次查询 _Population=_Population.take(10);//第二次查询

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

IQueryable 和 IEnumerable 的结论

    如果您正在针对数据库中的数据编写查询,那么 使用 IQueryable。 如果您正在查询处理中的数据,那么 使用 IEnumerable。 IEnumerable 有 GetEnumerator()、Current() 和 MoveNext() 方法。

【讨论】:

很高兴知道其中的区别。 (y) 扩展方法Take 是在IEnumerable&lt;T&gt; 上定义的。我验证了 只有 1 查询在这两种情况下都会被触发,无论是IEnumerable 还是IQueryable。只是IEnumerable 会进行内存过滤,这会将不需要的数据通过网络传输。

以上是关于IQueryable、ICollection、IList 和 IDictionary 接口之间的区别的主要内容,如果未能解决你的问题,请参考以下文章

IList,ICollection,IEnumerable,IEnumerator,IQueryable

EF ICollection Vs List Vs IEnumerable Vs IQueryable

EF下怎么理解IEnumerable/ICollection/IQueryable?

返回列表而不是IQueryable

IEnumerable 与 IQueryable 用于业务逻辑或 DAL 返回类型

C#中ICollection介绍