.NET:C# 如何实现的闭包?
背景
C# 在编译器层面为我们提供了闭包机制(Java7 和 Go 也是这种思路),本文简单的做个解释。
背景知识
你必须了解:引用类型、值类型、引用、对象、值类型的值(简称值)。
关于引用、对象和值在内存的分配有如下几点规则:
- 对象分配在堆中。
- 作为字段的引用分配在堆中(内嵌在对象中)。
- 作为局部变量(参数也是局部变量)的引用分配在栈中。
- 作为字段的值分配在堆中(内嵌在对象中)。
- 作为局部变量(参数也是局部变量)的值用分配在栈中。
- 局部变量只能存活于所在的作用域(方法中的大括号确定了作用域的长短)。
注:按值传递和按引用传递也是需要掌握的知识点,C# 默认是按值传递的。
闭包示例
测试代码
private static void Before()
{
Action[] actions = new Action[]; for (var i = ; i < actions.Length; i++)
{
actions[i] = () =>
{
Console.WriteLine(i);
};
} foreach (var item in actions)
{
item();
}
}
输出结果

编译器帮我们做了是什么?
编译器帮我们生成的代码(我自己写的,可以使用 Reflector 工具自己查看)
private static void After()
{
Action[] actions = new Action[]; var anonymous = new AnonymousClass(); for (anonymous.i = ; anonymous.i < actions.Length; anonymous.i++)
{
actions[anonymous.i ] = anonymous.Action;
} foreach (var item in actions)
{
item();
}
} class AnonymousClass
{
public int i; public void Action()
{
Console.WriteLine(this.i);
}
}
如何修复上面的问题?
上面的例子不是我们期望的输出,让我们给出两种修改方案:
第一种(借鉴JS)
private static void Fix()
{
Action[] actions = new Action[]; for (var i = ; i < actions.Length; i++)
{
new Action<int>((j) =>
{
actions[i] = () =>
{
Console.WriteLine(j);
};
})(i);
} foreach (var item in actions)
{
item();
}
}
第二种
public static void Fix2()
{
Action[] actions = new Action[]; for (var i = ; i < actions.Length; i++)
{
var j = i; actions[i] = () =>
{
Console.WriteLine(j);
};
} foreach (var item in actions)
{
item();
}
}
分析
编译器将闭包引用的局部变量转换为匿名类型的字段,导致了局部变量分配在堆中。
备注
C# 编译器帮我们做了非常多的工作,如:自动属性、类型推断、匿名类型、匿名委托、Lamda 表达式、析构方法、await 和 sync、using、对象初始化表达式、lock、默认参数 等等,这些统称为“语法糖”。
.NET:C# 如何实现的闭包?的更多相关文章
- 《Web 前端面试指南》1、JavaScript 闭包深入浅出
闭包是什么? 闭包是内部函数可以访问外部函数的变量.它可以访问三个作用域:首先可以访问自己的作用域(也就是定义在大括号内的变量),它也能访问外部函数的变量,和它能访问全局变量. 内部函数不仅可以访问外 ...
- 干货分享:让你分分钟学会 JS 闭包
闭包,是 Javascript 比较重要的一个概念,对于初学者来讲,闭包是一个特别抽象的概念,特别是ECMA规范给的定义,如果没有实战经验,很难从定义去理解它.因此,本文不会对闭包的概念进行大篇幅描述 ...
- 深入浅出JavaScript之闭包(Closure)
闭包(closure)是掌握Javascript从人门到深入一个非常重要的门槛,它是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现.下面写下我的学习笔记~ 闭包-无处不 ...
- javascript之闭包理解以及应用场景
半个月没写博文了,最近一直在弄小程序,感觉也没啥好写的. 之前读了js权威指南,也写了篇博文,但是实话实说当初看闭包确实还是一头雾水.现在时隔一个多月(当然这一段时间还是一直有在看闭包的相关知识)理解 ...
- js闭包 和 prototype
function test(){ var p=200; function q(){ return p++; } return q; } var s = test(); alert(s()); aler ...
- js闭包for循环总是只执行最后一个值得解决方法
<style> li{ list-style: none;width:40px;height: 40px;text-align:center;line-height: 40px;curso ...
- JavaScript学习笔记(二)——闭包、IIFE、apply、函数与对象
一.闭包(Closure) 1.1.闭包相关的问题 请在页面中放10个div,每个div中放入字母a-j,当点击每一个div时显示索引号,如第1个div显示0,第10个显示9:方法:找到所有的div, ...
- 带你一分钟理解闭包--js面向对象编程
上一篇<简单粗暴地理解js原型链--js面向对象编程>没想到能攒到这么多赞,实属意外.分享是个好事情,尤其是分享自己的学习感悟.所以网上关于原型链.闭包.作用域等文章多如牛毛,很多文章写得 ...
- 如何设计一门语言(七)——闭包、lambda和interface
人们都很喜欢讨论闭包这个概念.其实这个概念对于写代码来讲一点用都没有,写代码只需要掌握好lambda表达式和class+interface的语义就行了.基本上只有在写编译器和虚拟机的时候才需要管什么是 ...
- JavaScript 闭包深入浅出
闭包是什么? 闭包是内部函数可以访问外部函数的变量.它可以访问三个作用域:首先可以访问自己的作用域(也就是定义在大括号内的变量),它也能访问外部函数的变量,和它能访问全局变量. 内部函数不仅可以访问外 ...
随机推荐
- Linux Shell完成Qt程序的自动部署
#!/bin/sh #取当前脚本的绝对路径 srcDir=$(cd ")";pwd) #设置库所在路径 libDir=${srcDir}"/J1900RunLib/*&q ...
- ML.NET 示例:二元分类之用户评论的情绪分析
写在前面 准备近期将微软的machinelearning-samples翻译成中文,水平有限,如有错漏,请大家多多指正. 如果有朋友对此感兴趣,可以加入我:https://github.com/fei ...
- VS2010、VS2012、VS2013、VS2015、VS2017各版本产品激活秘钥
Visual Studio 2017(VS2017) 企业版 Enterprise 注册码:NJVYC-BMHX2-G77MM-4XJMR-6Q8QF Visual Studio 2017(VS201 ...
- dxteam团队项目终审报告
一. 团队成员的简介和个人博客地址 M1阶段 http://www.cnblogs.com/dxteam/p/3991514.html M2阶段 新成员 邓亚梅 http://www.cnblogs. ...
- 《Linux及安全》课程实践二
编译生成新内核 一.实践原理 Linux模块是一些可以作为独立程序来编译的函数和数据类型的集合.之所以提供模块机制,是因为Linux本身是一个单内核.单内核由于所有内容都集成在一起,效率很高,但可扩展 ...
- Linux环境C程序设计
Linux基础 常用shell命令 命令 说明 命令 说明 man 查看联机帮助 ls 查看目录及文件列表 cp 复制目录或文件 mv 移动目录或文件 cd 改变文件或目录 rm 删除文件或目录 mk ...
- Python学习笔记 -- 第六章 文件操作
I/O编程 在磁盘上读写文件的功能都是由操作系统提供的,现代操作系统不允许普通的程序直接操作磁盘,所以,读写文件就是请求操作系统打开一个文件对象(通常称为文件描述符),然后,通过操作系统提供的接口从这 ...
- 小学四则运算APP 第一个冲刺 第八天
团队成员:陈淑筠.杨家安.陈曦 团队选题:小学四则运算APP 第一次冲刺阶段时间:11.17~11.27 本次发布的是还未完成的功能二(选择题): ChoiceActivity.java: packa ...
- np.array与np.ndarray区别
(Numpy中ndarray和array的区别是什么?我在哪儿能够找到numpy中相应的实现?) 答:Well, np.array is just a convenience function to ...
- ubuntu在windows下的wubi安装
转自:http://mp.weixin.qq.com/s?__biz=MjM5NjYxNjU0OQ==&mid=200664819&idx=2&sn=25719890570b1 ...