Linq延迟执行
| 
 LINQ中大部分查询运算符都有一个非常重要的特性:延迟执行。这意味着,他们不是在查询创建的时候执行,而是在遍历的时候执行(换句话说,当enumerator的MoveNext方法被调用时)。让我们考虑下面这个query: static void TestDeferredExecution() 可以看出,我们在查询创建之后添加的number也包含在查询结果中了,这是因为直到foreach语句对query进行遍历时,LINQ查询才会执行,这时,数据源numbers已经包含了我们后来添加的元素2,LINQ的这种特性就是延迟执行。除了下面两种查询运算符,所有其他的运算符都是延迟执行的: 
 上面两种运算符会被立即执行,因为他们的返回值类型没有提供延迟执行的机制,比如下面的查询会被立即执行。 int matches = numbers.Where(n => (n % 2) == 0).Count(); // 1 对于LINQ来说,延迟执行时非常重要的,因为它把查询的创建与查询的执行解耦了,这让我们可以向创建SQL查询那样,分成多个步骤来创建我们的LINQ查询。 重复执行延迟执行带来的一个影响是,当我们重复遍历查询结果时,查询会被重复执行: static void TestReevaluation() 有时候,重复执行对我们说可不是一个优点,理由如下: 
 这个时候,我们就可以利用之前介绍的转换运算符,比如ToArray、ToList来避开重复执行,ToArray把查询结果保存至一个Array,而ToList把结果保存至泛型List<>: static void TestDefeatReevaluation() 变量捕获 延迟执行还有一个不好的副作用。如果查询的lambda表达式引用了程序的局部变量时,查询会在执行时对变量进行捕获。这意味着,如果在查询定义之后改变了该变量的值,那么查询结果也会随之改变。 static void TestCapturedVariable() 这个特性在我们通过foreach循环创建查询时会变成一个真正的陷阱。假如我们想要去掉一个字符串里的所有元音字母,我们可能会写出如下的query:               IEnumerable<char> query = "How are you, friend.";
            query = query.Where(c => c != 'a');
尽管程序结果正确,但我们都能看出,如此写出来的程序不够优雅。所以我们会自然而然的想到使用foreach循环来重构上面这段程序:             IEnumerable<char> query = "How are you, friend.";
            foreach(char vowel in "aeiou")
结果中只有字母u被过滤了,咋一看,有没有吃一惊呢!但只要仔细一想就能知道原因:因为vowel定义在循环之外,所以每个lambda表达式都捕获了同一变量。当我们的query执行时,vowel的值是什么呢?不正是被过滤的字母u嘛。要解决这个问题,我们只需把循环变量赋值给一个内部变量即可,如下面的temp变量作用域只是当前的lambda表达式。             IEnumerable<char> query = "How are you, friend.";
            foreach (char vowel in "aeiou")
        foreach (char i in "aeiou") foreach (char c in query) Console.Write(c); //Hw r y, frnd. 延迟执行的实现原理 查询运算符通过返回装饰者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 }
 在我们遍历query时,我们其实是在通过一个装饰者链来查询最初的array。 需要注意的是,如果在上面的查询后面加上一个转换运算符如ToList,那么query会被立即执行,这样,单个list就会取代上面的整个对象模型。  | 
Linq延迟执行的更多相关文章
- C#中Linq延迟执行问题
		
本文来自:http://msdn.microsoft.com/zh-cn/library/bb399393(v=vs.110).aspx http://www.cnblogs.com/zhanglin ...
 - linq 延迟执行带来的困扰
		
有这样一个案例: var filteredResult = from f in orgFileList select f; ; i < WorkStatusFilters.ListWorkSta ...
 - LINQ之路 6:延迟执行(Deferred Execution)
		
LINQ中大部分查询运算符都有一个非常重要的特性:延迟执行.这意味着,他们不是在查询创建的时候执行,而是在遍历的时候执行(换句话说,当enumerator的MoveNext方法被调用时).让我们考虑下 ...
 - Linq基础知识之延迟执行
		
Linq中的绝大多数查询运算符都有延迟执行的特性,查询并不是在查询创建的时候执行,而是在遍历的时候执行,也就是在enumerator的MoveNext()方法被调用的时候执行,大说数Linq查询操作实 ...
 - LINQ 学习路程 --  查询操作 Deferred Execution of LINQ Query 延迟执行
		
延迟执行是指一个表达式的值延迟获取,知道它的值真正用到. 当你用foreach循环时,表达式才真正的执行. 延迟执行有个最重要的好处:它总是给你最新的数据 实现延迟运行 你可以使用yield关键字实现 ...
 - LINQ 的查询执行何时是延迟执行,何时是立即执行,以及查询的复用
		
延迟执行的经典例子: 我们用 select ++i 就可以看到在foreach 时候,查询才被执行. public static void Linq99(){ int[] numbers = n ...
 - C#延迟执行
		
借鉴于该篇博客:http://kb.cnblogs.com/page/42581/ 先看两个方法 public class YieldClasses { public static IEnumerab ...
 - ThreadPoolTimer -延迟执行, 周期执行
		
介绍重新想象 Windows 8 Store Apps 之 线程池 通过 ThreadPoolTimer 实现延迟执行 通过 ThreadPoolTimer 实现周期执行 通过 ThreadPool ...
 - 浅谈iOS开发中方法延迟执行的几种方式
		
Method1. performSelector方法 Method2. NSTimer定时器 Method3. NSThread线程的sleep Method4. GCD 公用延迟执行方法 - (vo ...
 
随机推荐
- 【转】 Ubuntu samba服务器搭建及测试--不错
			
原文网址:http://blog.csdn.net/longfeey/article/details/5937968 Ubuntu samba服务配置是很不错的文件应用很有学习价值, 这里我主要讲解U ...
 - 【模拟】HDU 5762 Teacher Bo
			
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5762 题目大意: 给n个点,坐标范围0~m(n,m<=105),求是否存在2个点对满足哈夫曼距 ...
 - HDOJ 2072 单词数
			
Problem Description lily的好朋友xiaoou333最近很空,他想了一件没有什么意义的事情,就是统计一篇文章里不同单词的总数.下面你的任务是帮助xiaoou333解决这个问题. ...
 - 转:ORM框架
			
转自 程序员成长之路:http://blog.csdn.net/zxc22436/article/details/6875220 对象关系映射(ORM)提供了概念性的.易于理解的模型化数据的方法.OR ...
 - Python学习笔记2-flask-sqlalchemy 简单笔记
			
flask-sqlalchemy 简单笔记 字数 阅读 评论 喜欢 flask-sqlalchemy SQLAlchemy已经成为了python世界里面orm的标准,flask是一个轻巧的web框架, ...
 - Trie和Ternary Search Tree介绍
			
Trie树 Trie树,又称字典树,单词查找树或者前缀树,是一种用于快速检索的多叉树结构,如英文字母的字典树是一个26叉树,数字的字典树是一个10叉树. Trie树与二叉搜索树不同,键不是直接保存在节 ...
 - "ping: unknown host www.baidu.com" 解决方法
			
如果某台Linux服务器ping不通域名, 如下提示: # ping www.baidu.comping: unknown host www.baidu.com 如果确定网络没问题的情况下, 可以通过 ...
 - 1629 - Cake slicing(DP)
			
花了近2个小时终于AC,好爽.. 一道类似于最优矩阵链乘的题目,受<切木棍>那道题的启示,该题的原理也是一样的,仅仅只是变成了且面积.那么对应的也要添加维度 . 显然要完整的表示状态,最少 ...
 - 趣味算法——青蛙过河(JAVA)
			
青蛙过河是一个非常有趣的智力游戏,其大意如下: 一条河之间有若干个石块间隔,有两队青蛙在过河,每队有3只青蛙,这些青蛙只能向前移动,不能向后移动,且一次只能有一只青蛙向前移动.在移动过程中,青蛙可以向 ...
 - sql - 修改结构
			
1,修改表名 语法: sp_rename old_table_name, new_table_name 例如: sp_rename t_review, t_business 2,修改字段: MySQL ...
 
			
		
