c# 闭包

来源:互联网 发布:神通数据库 7.0 下载 编辑:程序博客网 时间:2024/05/22 00:37
  • 杂谈
        经常遇到这样的一种情况,看过的书或者网上Get的知识点,在很久没有使用之后,就会感觉不是自己的了。
        一个人的遗忘周期会根据你对某件事情的关注情况,而适时调整遗忘周期,最后忘记……
        我不想等到以后的某一天,突然回首自己工作的这段时光,发现,留下的除了经历蹉跎的岁月渐老的容颜之外,什么都没有剩下,所以,励志以后有时间就把某个知识点或者Get到的小技能记录下来。这样,当我某一天再回首的时候,会发现,除了蹉跎的岁月,我还有深刻的记忆以及感悟!!!

  •     本次记录的主题,实际上并不是我打算写系列博客的开篇。只是因为凑巧,公司的老前辈—-遥哥,在代码审查的时候,对我提交的一次代码进行点评的时候,对我这个(菜鸟)新手,提出的一个建议,建议我可以根据“闭包”做一次分享,既可以达到自己对该知识点的深入理解,又可以达到分享他人、共同提高的目的,于人于己,都有溢出,于是,在分享之后,有了这篇博客。
  • 引言
        明确两个概念
    1. 外部变量:
          作用域内包括匿名方法的局部变量或参数(不包括ref和out参数)。在类的实例成员内部的匿名方法中,this引用也被认为是一个外部变量。
    2. 捕获的外部变量:
          简称“捕获变量”。在匿名方法内部使用的外部变量。
      注:在明确了这两个概念之后,可以继续学习接下来的主题内容—-“闭包”
  • 正文
    1.     闭包概念(来自深入理解c#p132页):
              一个函数除了能通过提供给它的参数与外界交互之外,还能同环境进行更大的互动。
      注:
          这里的函数:匿名方法
          环境:该匿名方法捕获到的变量集
      eg:

注:第一个变量i不是外部变量的原因是因为它没有在匿名方法中使用;第二个变量j是外部变量,因为它在匿名方法中使用;第三个变量x不是外部变量,仅仅是一个局部变量。

    实际上,上面对闭包的概念稍显书面化,其它地方对闭包的解释:
        内层的函数可以引用包含在它外层的函数的变量,即使外层函数的执行已经终止。但该变量提供的值并非变量创建时的值,而是在
父函数范围内的最终值。(另外一种说法:闭包其实就是使用的变量已经脱离其作用域,却由于和作用域存在上下文关系,从而可以在当前环境中继续使用其上文环境中所定义的一种函数对象。)
eg:

这段代码的输出结果是什么呢?实际上输出结果是110.是不是感觉优点突兀,怎么可能?实际上就是如此。拿刚才的概念来说(先记得这样的概念)“但该变量提供的值并非变量创建时的值,而是在父函数范围内的最终值。”。那么,为什么会这样呢?通过Reflector工具查看生成的IL代码可以得到我们想要的答案。
eg:

下面是IL生成的一个类:

这里边包裹着一个存储i的字段:

原来:编译器生成IL代码后,将作用域外的变量i,放到了匿名类型‘<>c__DisplayClass0_0’中当做成员字段来使用,由此,本来应该在堆栈上的int型i,被编译器包装成了object类类型的成员字段,而object被存储在堆中。
稍微理清了一点闭包的思路,那么,闭包产生的条件是什么?
2. 闭包产生的条件:
1. 嵌套定义的函数
2. 匿名函数

3. 将函数作为参数或者返回值

  1. 闭包的优点
        实际上,我们知道,使用闭包,可以轻松的访问外层函数定义的变量,这在匿名方法中经常使用。
    eg:
  2. 示例分析
    eg:
    示例一:这个不是闭包,i仅仅是一个类的静态变量

示例二:

相当于下边的这个:

示例二第一张图生成的中间代码实际上如下:

示例二中的结果不是我们想要的,因此,就要避免这种闭包造成的影响,如何去做处理呢?c#中普遍的做法是,将匿名函数引用的变量用一个临时变量保存下来,然后在匿名函数中使用临时变量.
eg:

实际上相当于下边的这个图片:

生成的中间代码如下:

- 总结
1. 如果用或者不用捕获变量同样简单,那就不要用
2. 捕获由for或者foreach语句声明的变量之前,思考你的委托是否需要在循环迭代结
束之后延续,以及是否想让它看到那个变量的后续值。如果不想,就在循环内另建一
个变量,用来复制你想要的值。
3. 如果创建多个委托实例,而且捕获了变量,思考一下是否希望它们捕捉同一个变量。
4. 如果捕获的变量不会发生变化,就不需要担心。
5. 创建的委托实例永远不会从方法中逃脱(即不会存储在别的地方,不会返回,
也不会用于启动线程)
6. 从垃圾回收的角度,思考任何捕获变量被延长的生存期。

原创粉丝点击