借鉴于该篇博客:http://kb.cnblogs.com/page/42581/

先看两个方法

public class YieldClasses
{ public static IEnumerable<int> WithNoYied()
{
List<int> list = new List<int>(); for (int i = 0; i < 100; i++)
{
Console.Write(i.ToString());
list.Add(i);
}
return list; } public static IEnumerable<int> WithYied()
{
for (int i = 0; i < 100; i++)
{
Console.WriteLine(i.ToString());
yield return i;
}
} }

  分别用执行他们接过是怎样

YieldClasses.WithNoYied();

     YieldClasses.WithYied();??????

令人惊讶的是:第一个函数跟预期的一样,从1输到99。而第二个函数却什么 也没有输出!这是神马回事???

我们再foreach中迭代两个函数

 foreach (var item in YieldClasses.WithNoYied())
            {
                Console.Write(item.ToString()+"-");
            }
结果:
withYied的结果

withnoYied的结果:

1233456789101112.。。。。。。。0-1-2-3-4-5-6-7-8-9-10.。。。(突然截图不行了)

这是神马回事呢?

从显示的结果可以看出,在WithNoYied中,是先循环执行完函数中的console.write,再执行main中的write

而在WithYied中,是循环一次,先执行函数中的wirte,再执行main中的write,再循环下一次。。。。

这就是症结所在!明之:yield的延迟执行!

http://kb.cnblogs.com/page/42581/2/ 这里有用IL的方法分析。我就简单的总结以下吧:

延迟计算(Lazy evaluation或delayed evaluation)在Wiki上可以找到它的解释:将计算延迟,直到需要这个计算的结果的时候才计算,这样就可以因为避免一些不必要的计算而改进性能,在合成一些表达式时候还可以避免一些不必要的条件,因为这个时候其他计算都已经完成了,所有的条件都已经明确了,有的根本不可达的条件可以不用管了。反正就是好处很多了。

延迟计算来源自函数式编程,在函数式编程里,将函数作为参数来传递,你想呀,如果这个函数一传递就被计算了,那还搞什么搞,如果你使用了延迟计算,表达式在没有使用的时候是不会被计算的,比如有这样一个应用:x=expression,将这个表达式赋给x变量,但是如果x没有在别的地方使用的话这个表达式是不会被计算的,在这之前x里装的是这个表达式。

延迟计算在linq中的应用:

看看下面的方法:

public static void  LinqTest()
        {
            int[] intArray = {1,3,6,5,9,34 };
            int a=0;             var result = from item in intArray
                         select item;
            if(a==0)
            {
                foreach(int i in result)
                {
                    Console.Write(i);
                }
            }
        
        }
这样的方法,如果a==0,那会输出结果(先执行linq操作),但如果a!=0,那么linq操作就不执行!

result是一个实现了IEnumerable接口的类(在Linq里,所有实现了IEnumerable接口的类都被称作sequence),对它的foreach或者while的访问必须通过它对应的IEnumerator的MoveNext()方法,如果我们把一些耗时的或者需要延迟的操作放在MoveNext()里面,那么只有等到MoveNext()被访问,也就是result被使用的时候那些操作才会执行,而给result赋值啊,传递啊,什么的,那些耗时的操作都没有被执行。

如果上面这段代码,最后由于state小于0,而对result没有任何需求了,在Linq里返回的结果都是IEnumerable的,如果这里没有使用延迟计算,那那个Linq表达式不就白运算了么?如果是Linq to Objects还稍微好点,如果是Linq to SQL,而且那个数据库表又很大,真是得不偿失啊,所以微软想到了这点,这里使用了延迟计算,只有等到程序别的地方使用了result才会计算这里的Linq表达式的值的,这样Linq的性能也比以前提高了不少,而且Linq to SQL最后还是要生成SQL语句的,对于SQL语句的生成来说,如果将生成延迟,那么一些条件就先确定好了,生成SQL语句的时候就可以更精练了。还有,由于MoveNext()是一步步执行的,循环一次执行一次,所以如果有这种情况:我们遍历一次判断一下,不满足我们的条件了我们就退出,如果有一万个元素需要遍历,当遍历到第二个的时候就不满足条件了,这个时候我们就可就此退出,后面那么多元素实际上都没处理呢,那些元素也没有被加载到内存中来。

延迟计算还有很多惟妙惟肖的特质,也许以后你也可以按照这种方式来编程了呢。写到这里我突然想到了Command模式,Command模式将方法封装成类,Command对象在传递等时候是不会执行任何东西的,只有调用它内部那个方法他才会执行,这样我们就可以把命令到处发,还可以压栈啊等等而不担心在传递过程中Command被处理了,也许这也算是一种延迟计算吧。

本文也只是很浅的谈了一下延迟计算的东西,从这里还可以牵扯到并发编程模型和协同程序等更多内容,由于本人才疏学浅,所以只能介绍到这个地步了,上面一些说法也是我个人理解,肯定有很多不妥地方,欢迎大家拍砖。

												

C#延迟执行的更多相关文章

  1. ThreadPoolTimer -延迟执行, 周期执行

    介绍重新想象 Windows 8 Store Apps 之 线程池 通过 ThreadPoolTimer 实现延迟执行 通过 ThreadPoolTimer 实现周期执行 通过 ThreadPool ...

  2. 浅谈iOS开发中方法延迟执行的几种方式

    Method1. performSelector方法 Method2. NSTimer定时器 Method3. NSThread线程的sleep Method4. GCD 公用延迟执行方法 - (vo ...

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

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

  4. IOS中延迟执行的几种方法

    前几天去国美在线面试,就遇到了上面的问题,当时是笔试,只写出来了第一种方法,现在整理了一下. //1.performSelector方法:在当前线程中执行的方法,使用默认模式,并延迟执行@select ...

  5. js中的延迟执行和定时执行

    在js中,延迟执行函数有两种,setTimeout和setInterval,用法如下: function testFunction(){Console.log('hovertree.com');} s ...

  6. iOS定时器、延迟执行

    1.通用方式(并不是实时调用并且会卡顿): // 一般用于更新一些非界面上的数据 [NSTimer scheduledTimerWithTimeInterval:时间间隔 target:self se ...

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

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

  8. 重新想象 Windows 8 Store Apps (42) - 多线程之线程池: 延迟执行, 周期执行, 在线程池中找一个线程去执行指定的方法

    [源码下载] 重新想象 Windows 8 Store Apps (42) - 多线程之线程池: 延迟执行, 周期执行, 在线程池中找一个线程去执行指定的方法 作者:webabcd 介绍重新想象 Wi ...

  9. Go defer延迟执行

    defer用于延迟执行,可以类比于java或c++中的析构函数. 查看一段示例代码: func Contents(filename string) (string, error) { //打开文件 f ...

  10. SQL Server游标+延迟执行简介

    在项目测试中,我们可能会使用批量生成数据来测试程序的性能. 这里讲一个我遇到的问题,由于我们批量生成数据时基本上是瞬间完成,所以GETDATE()函数获得的时间基本上也是一样的,而我们又要求生成每条数 ...

随机推荐

  1. 第一章 安装ubuntu

    最近正在研究hadoop,hbase,准备自己写一套研究的感研,下面先讲下安装ubuntu,我这个是在虚拟机下安装,先用 文件转换的方式安装. 1:选择语言:最好选择英文,以免出错的时候乱码 2:选择 ...

  2. C语言实现Base64编码/解码

    Bse64是一种以64个可打印字符对二进制数据进行编码的编码算法.base64在对数据进行编码时以三个8位字符型数据为一组,取这三个字符型数据的ASCII码,然后以6位为一组组成4个新的数据,这4个新 ...

  3. 关于标签的属性-<a>

    标签的属性可以分成两个大类 1.系统属性名:例如 id class src这些都是系统里自带的 2.自定义属性名:可以根据使用的需要自行定义 下面我们简短介绍一下<a>标签的使用 < ...

  4. kafka常用命令(cdh5.10.0+kafka)

    参考资料:http://kafka.apache.org/quickstart 进入kafka安装目录(CDH安装路径为:/opt/cloudera/parcels/KAFKA):进入bin目录: c ...

  5. 如何实现查询显示N个工作日有效期内的数据

    功能点分析:要显示N个工作日有效期内的数据,需要考虑: 1. 可以给每条数据增加一个有效期时间字段,查询时只显示有效期之前的数据,如有效期为七天,数据的创建时间是2014-07-21,那七个工作日有效 ...

  6. sublime text安装插件

    http://www.sublimetext.com/ 安装Sublime Text 2插件的方法: 1.直接安装 安装Sublime text 2插件很方便,可以直接下载安装包解压缩到Package ...

  7. 0007-一套完整的CRUD_DEMO

    好久没写了,一直在忙别的东西,但是想想,还是把之前的补充完整好了.给大家一个参考,也为自己留个备份. 首先写一个Html作为内容载体,主要结构如下 <div ui-view="navb ...

  8. FastDFS:搭建文件管理系统

    文章转自:https://www.cnblogs.com/chiangchou/p/fastdfs.html#_label1 一.FastDFS介绍 FastDFS开源地址:https://githu ...

  9. Bootstrap 与 Jquery validate 结合使用——简单实现

    首先必须引入的JS和CSS <script type="text/javascript" src="${ctx}/static/js/jquery-1.9.1.mi ...

  10. LUA使用虚函数与使用回调函数

    ------------------虚函数overload-------------------------- --回调:寻路中格子坐标改变 CHero.OnSearchToCellsChange = ...