委托、Lambda表达式、事件系列05,Action委托与闭包
来看使用Action委托的一个实例:
static void Main(string[] args){int i = 0;Action a = () => i++;a();a();Console.WriteLine(i);}
结果是期望能的2。但令人好奇的是:栈上的变量i是如何传递给Action委托的?
反编译进行查看,首先看Main方法对应的IL代码:
再看c_DisplayClass1的IL代码:
从中可以看出:
→在托管堆上创建了一个名为c_DisplayClass1的实例
→把栈上变量i的值赋值给了c_DisplayClass1的实例字段i
→编译器() => i++;Lambda表达式表示的匿名委托起了个<Main>b_0的方法名,并成为了c_DisplayClass1的实例方法
→把c_DisplayClass1的实例方法<Main>b_0赋值给Action委托变量
→最后调用委托2次,这2次都是针对c_DisplayClass1的实例字段i
换句话说,在托管堆上创建了对象实例,形成"闭包"。栈上的变量变成了闭包的实例字段,Lambda表达式所表示的匿名委托变成了闭包的实例方法。
以上,创建了一个Action,形成了一个"闭包",接下来创建2个Action,形成2个"闭包",看"闭包"的实例字段是否相互影响?
static void Main(string[] args){Action a = GetAction();Action b = GetAction();Console.Write("第一次调用a,i的值=");a();Console.WriteLine();Console.Write("第二次调用a,i的值=");a();Console.WriteLine();Console.Write("第一次调用b,i的值=");b();Console.WriteLine();}static Action GetAction(){Action result = null;int i = 0;result = () => Console.Write(i++);return result;}
以上,虽然是把同一个GetAction方法分别赋值给了Action委托,但GetAction方法分别在不同的"闭包"内,当调用委托执行GetAction方法的时候,各自对闭包内的实例字段i自增1并打印,相互间不影响。
总结:每个Action都有自己的"闭包",并且"闭包"间互不影响。
“委托、Lambda表达式、事件系列”包括:
委托、Lambda表达式、事件系列01,委托是什么,委托的基本用法,委托的Method和Target属性
委托、Lambda表达式、事件系列02,什么时候该用委托
委托、Lambda表达式、事件系列03,从委托到Lamda表达式
委托、Lambda表达式、事件系列04,委托链是怎样形成的, 多播委托, 调用委托链方法,委托链异常处理
委托、Lambda表达式、事件系列05,Action委托与闭包
委托、Lambda表达式、事件系列06,使用Action实现观察者模式,体验委托和事件的区别
委托、Lambda表达式、事件系列07,使用EventHandler委托
委托、Lambda表达式、事件系列05,Action委托与闭包的更多相关文章
- 委托/lambda表达式/事件
委托 委托是执行安全的类,它的使用方式与类类似(即都需要定义再实例化),不同在于,类在实例化之后叫对象或类的实例,但委托在实例化后仍叫委托,委托可以把函数作为参数传递. 语法声明: delegate ...
- 委托+内置委托方法+多播委托+lambda表达式+事件
委托概念:如果我们要把方法当做参数来传递的话,就要用到委托.简单来说委托是一个类型,这个类型可以赋值一个方法的引用. 声明委托: 在C#中使用一个类分两个阶段,首选定义这个类,告诉编译器这个类由什么字 ...
- 委托、Lambda表达式、事件系列03,从委托到Lamda表达式
在"委托.Lambda表达式.事件系列02,什么时候该用委托"一文中,使用委托让代码简洁了不少. namespace ConsoleApplication2 { internal ...
- Unity C# 多态 委托 事件 匿名委托 Lambda表达式 观察者模式 .NET 框架中的委托和事件
一.多态 里氏替换原则: 任何能用基类的地方,可以用子类代替,反过来不行.子类能够在基类的基础上增加新的行为.面向对象设计的基本原则之一. 开放封闭原则: 对扩展开放,意味着有新的需求或变化时,可以对 ...
- C# Note2:委托(delegate) & Lambda表达式 & 事件(event)
前言 本文主要讲述委托和Lambda表达式的基础知识,以及如何通过Lambda表达式实现委托调用,并阐述.NET如何将委托用作实现事件的方式. 参考:C#高级编程 1.什么是委托(delegate)? ...
- (28)C#委托,匿名函数,lambda表达式,事件
一.委托 委托是一种用于封装命名和匿名方法的引用类型. 把方法当参数,传给另一个方法(这么说好理解,但实际上方法不能当参数,传入的是委托类型),委托是一种引用类型,委托里包含很多方法的引用 创建的方法 ...
- C#编程 委托 Lambda表达式和事件
委托 如果我们要把方法当做参数来传递的话,就要用到委托.简单来说委托是一个类型,这个类型可以赋值一个方法的引用. 声明委托 在C#中使用一个类分两个阶段,首选定义这个类,告诉编译器这个类由什么字段和方 ...
- 委托-异步调用-泛型委托-匿名方法-Lambda表达式-事件【转】
1. 委托 From: http://www.cnblogs.com/daxnet/archive/2008/11/08/1687014.html 类是对象的抽象,而委托则可以看成是函数的抽象.一个委 ...
- 委托 lambda表达式浅显理解
方法不能跟变量一样当参数传递,怎么办,C#定义了委托,就可以把方法当变量一样传递了,为了简单,匿名方法传递,省得再声明方法了:再简单,lambda表达式传递,比匿名方法更直观. public dele ...
随机推荐
- android休眠唤醒驱动流程分析【转】
转自:http://blog.csdn.net/hanmengaidudu/article/details/11777501 标准linux休眠过程: l power managemen ...
- 2012 Dhaka
2012 Dhaka B - Wedding of Sultan 题目描述:给出一棵树的\(dfs\)序(只要经过就会记录),求每个点的度 solution 按\(dfs\)序的规则还原这棵树就好了. ...
- vs 调试不进入断点
背景 或许当时环境不知发了什么神经,就是不调试了.竟然还有这种简单错误. 解决方案---配置管理器---选择debug模式
- Spring:@Cacheable 中condition条件的理解
condition=false时,不读取缓存,直接执行方法体,并返回结果,同时返回结果也不放入缓存. ndition=true时,读取缓存,有缓存则直接返回.无则执行方法体,同时返回结果放入缓存(如果 ...
- 部分Web服务器信息对比
本文参考wikipedia的Web服务器比较页面的数据,选取了其中自己感兴趣的Web服务器的信息进行了对比,包括,Apache HTTP Server.Apache Tomcat.Nginx.Catt ...
- 查找网内活跃IP和自动传输文本
ifconfig p32p1|egrep -o "broadcast [^ ]*" |grep -o "[0-9.]*"grep -o "broadc ...
- Java编程的逻辑 (19) - 接口的本质
本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http:/ ...
- Java编程的逻辑 (61) - 内存映射文件及其应用 - 实现一个简单的消息队列
本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http:/ ...
- Luogu 1903 数颜色 | 分块
Luogu 1903 数颜色 | 分块 莫队不会啊-- 这道题直接分块也能卡过! 这道题的做法很有趣:对于每个位置i,记录它的颜色a[i]上一次出现的位置,记为pre[i]. 这样在查询一个区间[l, ...
- 记2013年度成都MVP社区巡讲
上个周六在天府软件园A区的翼起来咖啡举行了MVP社区巡讲成都站的活动,这个巡讲活动去年也搞过一次. MVP社区巡讲是 @微软中国MVP项目组 支持的,由各地的MVP担任讲师,给本地技术社区提供的一种社 ...