浅谈.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 = ...
随机推荐
- 【Hibernate 5】继承映射配置及多态查询
一.继承实现的三种策略 1.1,单表继承.每棵类继承树使用一个表(table per class hierarchy) -->本文主要介绍的继承策略 类继承树对应多个类,要把多个类的信息存放在一 ...
- 使用SurfaceView播放RGB原始视频-2016.01.22
1 程序代码 使用Android中的SurfaceView播放RGB视频数据,SufaceView播放代码如下: package com.zhoulee.surfaceviewdemo; import ...
- hbase删除region块的脚本
删除hbase表region块脚本 文件hua.txt格式: CHAT_INFO,1318153079100530000314050,1318173760068.991ca04ff164c3f7987 ...
- 关于URL大小写问题
关于URL大小写的问题,不同平台的处理不同:Mac OS X 默认的文件系统(HFS case-insensitive) 是不分大小写的,Windows 上的 NTFS 也是,而 Linux 系统常用 ...
- 008sudo用户管理
1.Sudo是Unix/Linux平台上一个非常有用的工具,它允许系统管理员分配给普通用户一些合理的权利,让它们执行一些只有超级用户或其他特许用户才能完成的任务(主要体现为命令),比如,运行一些像mo ...
- Android IOS WebRTC 音视频开发总结(三四)-- windows.20150706
最近好不容易更新了PC版的WEBRTC,总结下有哪些调整,文章来自博客园RTC.Blacker,支持原创,转载请说明出处. 图1:解决方案工程结构对比: 说明: 1, 最大的调整就是移除了VideoE ...
- Easyui扩展或者重载(方法和属性)
1: 使用$.fn.datagrid.defaults.editors重载默认值. 每个编辑器都有以下方法: 名称 属性 描述 init container, options 初始化编辑器并返回目标对 ...
- Rich控件一
Calendar控件 Calendar控件用来在Web页面中显示日历中的可选日期,并显示与特定日期关联的数据. 控件声明代码如下: <asp: Calendar id=" Calend ...
- banner淡出效果
<div class="banner"> <div class="ban"></div> <ul class=&quo ...
- PHP版实现友好的时间显示方式(例如:2小时前)
完整php类,通常我会配合smary使用,快捷使用 (plugins/function.rdate.php),更多php技术开发就去php教程网,http://php.662p.com <?PH ...