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

Pra*_*eth 49 .net c# collections performance list

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

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

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

Joh*_*soe 105

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

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

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

  • 根据接口的通用版本,ICollection <T>支持添加/删除/清除/包含/复制到http://msdn.microsoft.com/en-us/library/92t2ye13.aspx (13认同)

RBT*_*RBT 5

我在@ gunny229的答案中注意到了几个问题,这就是为什么我写这篇文章的原因。我也在他的帖子的评论区域中提到了这些问题。要更正该帖子,我将不得不重写几乎整个帖子,因此我想创建自己的帖子。我无意整体解决OP的问题,但我想指出使用LINQ to SQL时IQueryable和IEnumerable之间区别

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

CREATE TABLE [dbo].[Employee]([PersonId] [int] NOT NULL PRIMARY KEY,[Salary] [int] NOT NULL)
Run Code Online (Sandbox Code Playgroud)

这是记录插入脚本(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
Run Code Online (Sandbox Code Playgroud)

现在我的目标是简单地从Employee数据库表中获取前2条记录。因此,我将ADO.NET实体数据模型项添加到指向Employee数据库中表的控制台应用程序中,并开始编写LINQ查询。

可查询路线的代码

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

当我开始运行该程序时,我还已经在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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

现在,事物被IEnumerable带到Salary表中存在的所有5条记录,然后在客户端计算机上执行内存中筛选以获取前2条记录。因此,多余的数据(在这种情况下为3条附加记录)已通过导线传输。