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. mysql报错排查总结

    mysql报错: [root@zabbix ~]# mysql ERROR 2002 (HY000): Can't connect to local MySQL server through sock ...

  2. HDU 2546 饭卡 (01背包问题)

    题意:中文的吧,飘过~ 析:学过DP的都应该感觉到是动态规划吧,就是一个01背包问题,不同的是,这个题又加入一些新的条件,就是不满5元不能消费,过了5元即使超了也行(这个学校真不错,都可以预支),最后 ...

  3. html 源码 引入样式

    post-title2 示例 sdf post-title 示例

  4. authentication 和 authorization

    单词 词性 解释 authentication n. 认证 authentic adj. 真实的 authorization n. 授权 authorise vt. 授权 authentication ...

  5. spring boot打包后windows启动乱码

    事情的起因什么的就不多表了,直接进入主题... 项目都要上线了,结果发现使用 idea mvn install之后的 jar在windows下启动乱码,而使用idea启动却没有问题!!! 这是神马情况 ...

  6. hdu 4998 矩阵表示旋转

    http://acm.hdu.edu.cn/showproblem.php?pid=4998 http://blog.csdn.net/wcyoot/article/details/33310329 ...

  7. oracle数据库查询日期sql语句(范例)、向已经建好的表格中添加一列属性并向该列添加数值、删除某一列的数据(一整列)

    先列上我的数据库表格: c_date(Date格式)     date_type(String格式) 2011-01-01                   0 2012-03-07         ...

  8. (原创)Hibernate 使用过程中(尤其是多对多关联中的级联保存和级联删除)的注意事项(基于项目的总结)

    一.先上知识点: 1.hibernate多对多关联关系中最重要的参数是(基于配置文件xxx.hbm.xml文件形式): 1):inverse属性,如果设置inverse=“true”就代表让对方参与维 ...

  9. 集合(五)不正确地使用HashMap引发死循环及元素丢失

    前一篇文章讲解了HashMap的实现原理,讲到了HashMap不是线程安全的.那么HashMap在多线程环境下又会有什么问题呢? 几个月前,公司项目的一个模块在线上运行的时候出现了死循环,死循环的代码 ...

  10. Delphi for iOS开发指南(7):在iOS应用程序中使用WebBrowser组件

    Delphi for iOS开发指南(7):在iOS应用程序中使用WebBrowser组件 在FireMonkey iOS应用程序中使用WebBrowser 在iOS平台上,FireMonkey使用T ...