C# 中闭包(Closure)详解
C# 中闭包(Closure)详解
这个问题是在最近一次英格兰 Brighton ALT.NET Beers 活动中提出来的。我发现,如果不用代码来演示,你很难单用话语把它解释清楚,所以,在这里,我打算用 C# 来解释一下什么是闭包(closures)。维基百科上说:
在计算机科学中,闭包(Closure)是词法闭包(Lexical Closure)的简称,是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。
所以,一个闭包就是一个“捕获”或“携带”了其被生成的环境中、所属的变量范围内所引用的所有变量的函数。的确,很难描述,但当你看完了这些代码后,你就很容易理解了。
var x = 1; Action action = () => { var y = 2; var result = x + y; Console.Out.WriteLine("result = {0}", result); }; action();
这里我们首先定义了一个变量“x”,值为1。然后我们定义了一个匿名函数(一个 lambda 表达式)赋给类型 Action。Action 没有参数, 没有返回值,但如果你观察“action”里的定义,你会发现它使用了“x”变量。这是变量是被 action“捕获”或“携带”的,自动被添加到了 action 的运行环境中了。
当我们执行 action 时,它输出了我们预期的结果。请注意,当我们执行时,原始的“x”此时已经脱离了它当初的变量环境,但它仍然能用。
当你在代码调试器(debugger)里观察“action”时,会发现很有趣的事情。我们可以看到,C# 编译器为我们创建了一个 Target 类,里面封装了 x 变量:
闭包(Closure)
闭包(和 higher order functions)都是非常有用的东西。如果你曾经开发过稍微复杂一点的 JavaScript 程序,你可能就会知道,这个东西可以被当成很多面向对象特征的替代品,就像 C# 那样。前不久我还在 C# 里写了一个例子来验证这种想法。
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
相关推荐
-
c#闭包使用方法示例
代码简单,直接上代码了 复制代码 代码如下: private static void Before() { Action[] actions = new Action[10]; for (var i = 0; i < actions.Length; i++) { actions[i] = () => { Console.WriteLine(
-
C#中函数的创建和闭包的理解
动态创建函数 大多数同学,都或多或少的使用过.回顾下c#中动态创建函数的进化: C# 1.0中: 复制代码 代码如下: public delegate string DynamicFunction(string name); public static DynamicFunction GetDynamicFunction() { return GetName; } static string GetName(string name) { return
-
C#函数式程序设计之用闭包封装数据的实现代码
C#函数式程序设计之作用域 在C#中,变量的作用域是严格确定的.其本质是所有代码生存在类的方法中.所有变量只生存于声明它们的模块中或者之后的代码中.变量的值是可变的,一个变量越是公开,带来的问题就越严重.一般的原则是,变量的值最好保持不变,或者在最小的作用域内保存其值.一个纯函数最好只使用在自己的模块中定义的变量值,不访问其作用域之外的任何变量. 遗憾的是,有时我们无法把变量的值限制于函数的范围内.如果在程序的初始化时定义了几个变量,在后面需要反复用到它们,怎么办?一个可能的办法是使用闭包. C
-
C# 中闭包(Closure)详解
C# 中闭包(Closure)详解 这个问题是在最近一次英格兰 Brighton ALT.NET Beers 活动中提出来的.我发现,如果不用代码来演示,你很难单用话语把它解释清楚,所以,在这里,我打算用 C# 来解释一下什么是闭包(closures).维基百科上说: 在计算机科学中,闭包(Closure)是词法闭包(Lexical Closure)的简称,是引用了自由变量的函数.这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外.所以,有另一种说法认为闭包是由函数和与
-
javascript中闭包(Closure)详解
在javascript中,函数可看作是一种数据,可以赋值给变量,可以嵌套在另一个函数中. var fun = function(){ console.log("平底斜"); } function fun(){ var n=10; function son(){ n++; } son(); console.log(n); } fun(); //11 fun(); //11 我们把上面第二段代码稍微修改下: var n=10; function fun(){ function son(){
-
JavaScript中闭包的详解
闭包是什么 在 JavaScript 中,闭包是一个让人很难弄懂的概念.ECMAScript 中给闭包的定义是:闭包,指的是词法表示包括不被计算的变量的函数,也就是说,函数可以使用函数之外定义的变量. 是不是看完这个定义感觉更加懵逼了?别急,我们来分析一下. 闭包是一个函数 闭包可以使用在它外面定义的变量 闭包存在定义该变量的作用域中 好像有点清晰了,但是使用在它外面定义的变量是什么意思,我们先来看看变量作用域. 变量作用域 变量可分为全局变量和局部变量.全局变量的作用域就是全局性的,在 js
-
JavaScript中最容易混淆的作用域、提升、闭包知识详解(推荐)
一.函数作用域 1.函数作用域 就是作用域在一个"Function"里,属于这个函数的全部变量都可以在整个函数的范围内使用及复用. function foo(a) { var b = 2; function bar() { // ... } var c = 3; } bar(); // 失败 console.log( a, b, c ); // 三个全都失败 上面的"foo"函数内的几个标识符,放到函数外面访问就都会报错. 2.立即执行函数表达式 在任意代码片段外部
-
kotlin之闭包案例详解
闭包,函数式编程福音 先了解函数式编程(Functional Programming) 概念:它属于"结构化编程"的一种,主要思想是把运算过程尽量写成一系列嵌套的函数调用.函数式编程语言最重要的基础是λ运算(Lambda表达式),λ运算的函数可以接受函数当做参数或返回值. 对比函数式编程与面向对象编程 面向对象编程(Object-oriented programming,缩写OOP) 面向对象编程是一种具有对象概念的程序编程范型,它可能包含数据.属性.方法.它将对象作为程序的基本单元,
-
Java中的静态内部类详解及代码示例
1. 什么是静态内部类 在Java中有静态代码块.静态变量.静态方法,当然也有静态类,但Java中的静态类只能是Java的内部类,也称为静态嵌套类.静态内部类的定义如下: public class OuterClass { static class StaticInnerClass { ... } } 在介绍静态内部类之前,首先要弄清楚静态内部类与Java其它内部类的区别. 2. 内部类 什么是内部类?将一个类的定义放在另一个类的内部,就是内部类.Java的内部类主要分为成员内部类.局部内部类.
-
Mysql中explain作用详解
一.MYSQL的索引 索引(Index):帮助Mysql高效获取数据的一种数据结构.用于提高查找效率,可以比作字典.可以简单理解为排好序的快速查找的数据结构. 索引的作用:便于查询和排序(所以添加索引会影响where 语句与 order by 排序语句). 在数据之外,数据库还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用数据.这样就可以在这些数据结构上实现高级查找算法.这些数据结构就是索引. 索引本身也很大,不可能全部存储在内存中,所以索引往往以索引文件的形式存储在磁盘上. 我们
-
linux中 pmap 命令详解
通过查看帮助,返回了如下信息: Usage: pmap [options] pid [pid ...] Options: -x, --extended show details -X show even more details WARNING: format changes according to /proc/PID/smaps -XX show everything the kernel provides -c, --read-rc read the default rc -C, --re
-
linux 中ls命令详解
ls命令用来显示目标列表,在Linux中是使用率较高的命令.ls命令的输出信息可以进行彩色加亮显示,以分区不同类型的文件. 语法 ls(选项)(参数) 选项 -a:显示所有档案及目录(ls内定将档案名或目录名称为“.”的视为影藏,不会列出): -A:显示除影藏文件“.”和“..”以外的所有文件列表: -C:多列显示输出结果.这是默认选项: -l:与“-C”选项功能相反,所有输出信息用单列格式输出,不输出为多列: -F:在每个输出项后追加文件的类型标识符,具体含义:“*”表示具有可执行权限的普通文
-
Linux 中的通配符详解及实例
Linux 中的通配符详解及实例 一 通配符 二 实战 [root@localhost ~]# mkdir dy [root@localhost ~]# cd dy [root@localhost dy]# touch dzp dzp2 dzp3 dzp34 dzpcang dzpbols [root@localhost dy]# ls dzp dzp2 dzp3 dzp34 dzpbols dzpcang [root@localhost dy]# la dzp bash: la: comma
随机推荐
- jQuery构造函数init参数分析
- 金山反病毒20050103_日报
- 详解直接插入排序算法与相关的Java版代码实现
- 通过JS和PHP两种方法判断用户请求时使用的浏览器类型
- AJAX和jQuery动态加载数据的实现方法
- C语言打印杨辉三角示例汇总
- 反SPAM新思路—换Z-BLOG的验证码!
- 查找最新的文件的批处理bat文件
- Mac下Nginx安装环境配置详解
- Mybatis批量更新报错问题
- Python二维码生成库qrcode安装和使用示例
- Oracle表空间查看sql使用情况
- 符合web标准的连续滚动图像的js代码
- android截屏功能实现代码
- jquery 提示信息显示后自动消失的具体实现
- Javascript中document.referrer隐藏来源的方法
- javascript 随机展示头像实现代码
- Android实现将View保存成Bitmap的方法
- Android 自定义View实现芝麻分曲线图效果
- 浅谈React 服务器端渲染的使用