Linq中的绝大多数查询运算符都有延迟执行的特性,查询并不是在查询创建的时候执行,而是在遍历的时候执行,也就是在enumerator的MoveNext()方法被调用的时候执行,大说数Linq查询操作实例方法返回的都是IEnumerable<T>,所以只有在使用foreach遍历的时候,查询方法才能被真正的执行.请参考C# 通过IEnumberable接口和IEnumerator接口实现自定义集合类型foreach功能

示例代码如下:

List<int> list=new List<int>();
list.AddRange(new int[]{ , , , , });
IEnumerable<int> result = list.Where(n => n >= );
list.Add();
foreach (var n in result)
{
Console.WriteLine(n);
}

输出结果一目了然,当创建完查询之后添加的元素也包含到了结果集中,说明查询并没有立即执行,而是在使用foreach遍历之后才执行,这种特性就是Linq的延迟执行.

不止Where查询操作符是这样的,其他的只要返回的是IEnumerable<T>对象的都有延迟执行特性.

注:其他的一些像First、Count、ToArray、ToList、ToDictionary、ToLookup这些都是立即执行的.

当然,对于Linq来说,延迟执行是非常重要的,因为它把查询的创建和查询的执行解耦了,这让我们可以像创建SQL查询那样,分成多个步骤来创建我们的LINQ查询。

重复执行

使用导致延迟执行的查询操作符进行查询操作,并且两次或者两次以上的使用foreach,会导致查询重复执行,重复执行在以下两种情况下,绝对是不好的:

1、当需要在一个确定点保存查询的结果时,因为延迟执行并不会在创建查询之后马上得到查询结果集,所以必须使用上面提到的ToArray、ToList等方法使查询立即执行得到结果集并进行存储,代码如下:

List<int> list=new List<int>();
list.AddRange(new int[]{ , , , , });
IEnumerable<int> result = list.Where(n => n >= ).ToList();
list.Add();
foreach (var n in result)
{
Console.WriteLine(n);
}

例子不是贴切,但是意思到了,此时的查询是立即执行.

2、有些查询比较耗时,比如对一个非常大的数据集进行操作或者通过Linq远程操作数据库操作数据时,这个时候的重复执行会严重影响性能.

延迟执行的实现原理

查询运算符通过返回装饰者sequence(decorator sequence)来支持延迟执行。

和传统的集合类型如array,linked list不同,一个装饰者sequence并没有自己用来存放元素的底层结构,而是包装了我们在运行时提供的另外一个sequence。此后当我们从装饰者sequence中请求数据时,它就会转而从包装的sequence中请求数据。

比如调用Where会创建一个装饰者sequence,其中保存了输入sequence的引用、lambda表达式还有其他提供的参数。下面的查询对应的装饰者sequence如图所示:

        IEnumerable<int> lessThanTen = new int[] { 5, 12, 3 }.Where(n => n < 10);

当我们遍历lessThanTen时,实际上我们是在通过Where装饰者从Array中查找数据。

而查询运算符链接创建了一个多层的装饰者,每个查询运算符都会实例化一个装饰者来包装前一个sequence,比如下面的query和对应的多层装饰者sequence:

            IEnumerable<int> query = new int[] { 5, 12, 3 }
.Where(n => n < 10)
.OrderBy(n => n)
.Select(n => n * 10);

在我们遍历query时,我们其实是在通过一个装饰者链来查询最初的array。

需要注意的是,如果在上面的查询后面加上一个转换运算符如ToList,那么query会被立即执行,这样,单个list就会取代上面的整个对象模型。

Linq基础知识之延迟执行的更多相关文章

  1. Linq基础知识小记四之操作EF

    1.EF简介 EF之于Linq,EF是一种包含Linq功能对象关系映射技术.EF对数据库架构和我们查询的类型进行更好的解耦,使用EF,我们查询的对象不再是C#类,而是更高层的抽象:Entity Dat ...

  2. Linq基础知识小记三

    1.子查询 Linq中的子查询思想和Sql中的子查询其实差不多, 对于方法语法,一个子查询包含在另一个子查询的Lambda表达式中,代码如下: string[] names = { "Jam ...

  3. Linq基础知识小记二

    书写Linq查询有两种方法,第一种是通过方法语法(也就是扩展方法),第二种是查询表达式语法. 1.方法语法 方法语法就是通过扩展方法和Lambda表达式来创建查询 (1).链式查询 这种查询方式很多语 ...

  4. Linq基础知识小记一

    1.LINQ(语言级集成查询)的作用就是提供一种统一且对称的方式,让程序员在广义的数据上获取和操作数据.广义的数据包括XML文档数据.元数据.System.Data.dll和System.Data.S ...

  5. Linq基础知识

    开发人员不需要关心将要访问的是关系数据库还是XML数据,或是远程对象,它都采用同样的访问方式. Linq包含一系列的查询技术,其中Linq到对象是对内存进行操作,LINQ到SQL是对数据库的操作,LI ...

  6. LINQ之路 6:延迟执行(Deferred Execution)

    LINQ中大部分查询运算符都有一个非常重要的特性:延迟执行.这意味着,他们不是在查询创建的时候执行,而是在遍历的时候执行(换句话说,当enumerator的MoveNext方法被调用时).让我们考虑下 ...

  7. linq 延迟执行带来的困扰

    有这样一个案例: var filteredResult = from f in orgFileList select f; ; i < WorkStatusFilters.ListWorkSta ...

  8. Linq延迟执行

    LINQ中大部分查询运算符都有一个非常重要的特性:延迟执行.这意味着,他们不是在查询创建的时候执行,而是在遍历的时候执行(换句话说,当enumerator的MoveNext方法被调用时).让我们考虑下 ...

  9. C#中Linq延迟执行问题

    本文来自:http://msdn.microsoft.com/zh-cn/library/bb399393(v=vs.110).aspx http://www.cnblogs.com/zhanglin ...

随机推荐

  1. Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [com.liuyang.JDbCTemplate.PersonDao]: No default constructor fo

    错误是说我的配置文件中没有对构造函数进行配置,所以找不到构造函数,在配置文件application.xml中加入如下句子: <bean id="personDao" clas ...

  2. UVa 11992 Fast Matrix Operations (线段树,区间修改)

    题意:给出一个row*col的全0矩阵,有三种操作 1 x1 y1 x2 y2 v:将x1 <= row <= x2, y1 <= col <= y2里面的点全部增加v: 2 ...

  3. (匹配)Dolls --HDU --4160

    链接: http://acm.hdu.edu.cn/showproblem.php?pid=4160 代码: #include<stdio.h> #include<string.h& ...

  4. 20155223 2016-2017-2 《Java程序设计》第9周学习总结

    20155223 2016-2017-2 <Java程序设计>第9周学习总结 教材学习内容总结 第十六章 JDBC--Java数据库连接是用于执行SQL的解决方案,开发人员无需接触底层数据 ...

  5. POJ3045 Cow Acrobats 2017-05-11 18:06 31人阅读 评论(0) 收藏

    Cow Acrobats Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4998   Accepted: 1892 Desc ...

  6. HDU6024 Building Shops 2017-05-07 18:33 30人阅读 评论(0) 收藏

    Building Shops                                                             Time Limit: 2000/1000 MS ...

  7. hdu5883 The Best Path 2016-09-21 21:31 92人阅读 评论(0) 收藏

    The Best Path Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) To ...

  8. Alpha阶段项目复审(小小大佬带飞队)

    Alpha阶段项目复审 小组的名字 优点 缺点,bug报告(至少140字) 最终名次(无并列) 只会嘤嘤嘤队 题材比较新颖!游戏和记单词的结合  有浏览器不兼容问题 5 GG队 样式新颖,自动导入好评 ...

  9. php连接微软MSSQL(sql server)完全攻略

    http://www.jb51.net/article/98364.htm php连接微软MSSQL(sql server)完全攻略 作者:吵吵 字体:[增加 减小] 类型:转载 时间:2016-11 ...

  10. DBCC--常用跟踪标记

    使用DBCC TRACEON 和DBCC TRACEOFF来打开和关闭跟踪标记 使用DBCC TRACESTATUS来查看所有打开的跟踪标记 --260:打印关于扩展存储过程动态链接库的版本信息 -- ...