浅谈.NET中闭包
什么是闭包
闭包可以从而三个维度来说明。在编程语言领域,闭包是指由函数以及与函数相关的上下文环境组合而成的实体。通过闭包,函数与其上下文变量之间建立起关联关系,上下文变量的状态可以在函数的多次调用过程中持久保持。从作用域而言,私有变量的生命周期被延长,函数调用所生成的值在下次调用时仍被保持。从安全性而言,闭包有利于信息的隐蔽,私有变量只在该函数内可见。
.NET中的闭包
说起闭包,可对会想起JavaScript。在JavaScript语言中,闭包可以说是无处不在。同样,.NET中也有闭包。只不过实现方式和JavaScript不太一样。
通常而言,形成闭包有一些值得总结的非必要条件:
- 嵌套定义函数
- 匿名函数
- 将函数作为参数或返回值
在.NET中,函数并不是第一级成员,所以并不能像JavaScript那样通过嵌套子函数的方式实现闭包。但.NET可以通过匿名委托形成闭包。
delegate void HelloDelegate();
static void Main(string[] args)
{
string str = "Hello World!"; HelloDelegate hello = delegate()
{
Print(str);
};
} private static void Print(string str)
{
Console.WriteLine(str);
}
反编译上面的IL代码:

如上图所示,编译器自动生成了一个内部类,变量strb变成这个类的字段,即使创建该变量的方法(Main)执行结束,该变量也不会释放,而是在所有回调函数执行之后才被GC回收。这就是.NET实现闭包的原理。
闭包带来的问题
如下面代码:
static void Main()
{
IList<Action> actions = new List<Action>(); for (int i = 0; i < 5; i++)
{
actions.Add(() => Console.WriteLine(i));
} foreach (var action in actions)
{
action();
}
}
先猜猜输入的值是什么,如果猜的0、1、2、3、4的话就错了。应该全是4。那为什么呢?因为闭包具有延迟的和数据共享的特性,只有当调用action()方法时才会获取i的值,这是i的值经过i++已经变成4,又因为所有的action都会获取同一个i值,所以最后输出的值都为4。
那怎么解决呢?通常解决方法时在循环中加入中间量。
for (int i = 0; i < 5; i++)
{
int j = i;
actions.Add(() => Console.WriteLine(j));
}

浅谈.NET中闭包的更多相关文章
- 浅谈JavaScript中闭包
引言 闭包可以说是JavaScript中最有特色的一个地方,很好的理解闭包是更深层次的学习JavaScript的基础.这篇文章我们就来简单的谈下JavaScript下的闭包. 闭包是什么? 闭包是什么 ...
- 浅谈JavaScript中的闭包
浅谈JavaScript中的闭包 在JavaScript中,闭包是指这样一个函数:它有权访问另一个函数作用域中的变量. 创建一个闭包的常用的方式:在一个函数内部创建另一个函数. 比如: functio ...
- 浅谈JS中的闭包
浅谈JS中的闭包 在介绍闭包之前,我先介绍点JS的基础知识,下面的基础知识会充分的帮助你理解闭包.那么接下来先看下变量的作用域. 变量的作用域 变量共有两种,一种为全局变量,一种为局部变量.那么全局变 ...
- 浅谈 .NET 中的对象引用、非托管指针和托管指针 理解C#中的闭包
浅谈 .NET 中的对象引用.非托管指针和托管指针 目录 前言 一.对象引用 二.值传递和引用传递 三.初识托管指针和非托管指针 四.非托管指针 1.非托管指针不能指向对象引用 2.类成员指针 五 ...
- 浅谈JS中 var let const 变量声明
浅谈JS中 var let const 变量声明 用var来声明变量会出现的问题: 1. 允许重复的变量声明:导致数据被覆盖 2. 变量提升:怪异的数据访问.闭包问题 3. 全局变量挂载到全局对象:全 ...
- 浅谈Java中的equals和==(转)
浅谈Java中的equals和== 在初学Java时,可能会经常碰到下面的代码: 1 String str1 = new String("hello"); 2 String str ...
- 浅谈Linux中的信号处理机制(二)
首先谢谢 @小尧弟 这位朋友对我昨天夜里写的一篇<浅谈Linux中的信号处理机制(一)>的指正,之前的题目我用的“浅析”一词,给人一种要剖析内核的感觉.本人自知功力不够,尚且不能对着Lin ...
- 浅谈Java中的对象和引用
浅谈Java中的对象和对象引用 在Java中,有一组名词经常一起出现,它们就是“对象和对象引用”,很多朋友在初学Java的时候可能经常会混淆这2个概念,觉得它们是一回事,事实上则不然.今天我们就来一起 ...
- 浅谈Java中的equals和==
浅谈Java中的equals和== 在初学Java时,可能会经常碰到下面的代码: String str1 = new String("hello"); String str2 = ...
随机推荐
- mysql 常用sql操作语句
获取数据库里所有表 SELECT TABLE_NAME,TABLE_ROWS FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='数据库名' 获取表里 ...
- angular directive指令的复用
“指令之之所以要定义成指令就是为了复用!” 指令一定是可以用在不同的controller里面的,为了在不同的controller去使用它,我们一定要给指定的配置项一个指令.这样才能跟外面的控制器进行交 ...
- Shell的概念
Linux系统分为三个重要部分: 1:kernel(核心) 2:Shell 3:应用程序和工具
- Send User to a Portal Folder
Sometimes you would want to give users the option to click a button on the page and send them back t ...
- C#访问配置文件
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.R ...
- nginx 编译安装
一.安装nginx时必须先安装相应的编译工具yum -y install gcc gcc-c++ autoconf automakeyum -y install zlib zlib-devel ope ...
- php对mysql简单读取的实例
读取mysql数据库 例. <?php $link=mysql_connect("localhost","root","之前的管理员密码& ...
- B-树
定义: B-树是一种平衡的多路查找树,在文件系统中有所应用.主要用作文件的索引. 特性:(M为层数) 1.定义任意非叶子结点最多只有M个儿子:且M>2: 2.根结点的儿子数为[2, M]: 3. ...
- delphi控件安装与删除
附带通用控件安装方法:----------基本安装1.对于单个控件,Componet-->install component..-->PAS或DCU文件-->install;2.对于 ...
- Oracle 查看相关优化器参数
select x.ksppinm name, y.ksppstvl value, y.ksppstdf isdefault, decode(bitand(y.ksppstvf, 7), 1, 'MOD ...