10.C#匿名函数的变量捕获(五章5.5)
首先感谢园友的指定,后续的文章一定会多码多想,出来的文章才有说服力。那今天接上篇我们来聊一聊匿名函数,对于匿名函数,我们知道使用delegate关键字,那我们来需要知道匿名函数在变量是的处理方式,先说两个术语,外部变量和捕获的外部变量,可以看出"捕获的外部变量=外部变量+捕获了",这个捕获顾名思义就是在匿名函数中使用了这个变量。
外部变量:指在一个包含匿名方法的作用域内的变量或者参数,在类的实例成员内部的匿名方法,this也是认为是一个外部变量。
捕获的外部变量:它是指在匿名方法中使用的外部变量。
代码如下
static void Main(string[] args)
{
//x和y称为外部变量
int x = , y = ;
//在匿名方法中使用到了x,则x称为捕获的外部变量
Action<int> ac = delegate (int n) { Console.WriteLine(x); }; //小结:x、y和匿名方法都在Main函数的作用域内,也可以扩展到类的作用域及命名空间的作用域 Console.ReadKey();
}
再来说下匿名方法捕获变量的行为,可以看到在匿名方法中我们访问到了局部变量x,请注意,并不是仅仅访问到了x的值,而是在匿名类型中使用一个类型实例引用到了变量x,对于x的改变,因为是引用,所以总能使用这个类型实例访问到,如
long x1 = , y1 = ;
Action<long> ac1 = delegate (long l) { Console.WriteLine(x1); };
ac1(1L); //打印11
x1 = y1;
ac1(1L); //打印12
参数long l这里没有使用到,不过这里的参数不是上面所说的外部变量,因为它确实是匿名方法的参数
static void Debug(int x) {
Action<int> a = delegate (int y) { Console.WriteLine(x); };
}
上面的x就是术语中说的外部变量,分清定义就应该没问题了吧。
关于变量的生存周期,可以就只在一个作用域内,当代码执行完这个作用域,该作用域内的变量也会被销毁,但使用匿名方法可以延长变量的生存周期。
static void Main(string[] args)
{
GetLen gl = GetMethod();
gl("s"); //打印00s
gl("s"); //打印0000s Console.ReadKey();
} public delegate int GetLen(string s);
static GetLen GetMethod()
{
string temp = "";
return delegate (string s) {
temp = String.Concat(temp, temp);
s = String.Concat(temp, s);
Console.WriteLine(s);
return s.Length;
};
}
看出使用GetMethod返回一个委托,这里使用匿名函数(因为匿名函数就是对应签名的委托),在正常理解下temp在GetMethod作用域内,当离开作用域外,这个变量会销毁,但说过匿名函数会使用一个类型实例引用这个变量,则这个变量不会销毁,只有当匿名函数销毁(也就是委托)才会跟着销毁,从而延长了变量的作用域,而且对于temp变量的操作也会直接反应在实例引用的变量上,如第一次调用gl("s"),temp="00",第二次调用时,temp="0000"。
最后说下有点绕的东西,就是变量的实例化在匿名函数中的访问规则,不过个人感觉这个还真是不很绕,还算是比较好理解的。看下代码。
GetLen[] a = { };
int xx = ;
for (int i = ; i < ; i++)
{
int xxx = i;
a[i] = delegate (string s) {
xx++;
xxx++;
return xx + xxx;
};
}
a是一个委托数组,对于数组中每一个委托都共享一个xx实例引用,而每一个委托都各自拥有一个xxx实例引用(xxx对应不同的委托是不同的),这是因为在循环中,每一次的循环都实例化了xxx,则对于各个委托都有一个全新的xxx实例引用,而xx则是在循环之外实例化的,则每个委托共享一个实例引用。当然在实际的使用过程中,不可能那么简单,那么要我们开动大脑,好好区别哪一个共享的,哪一个是独自引用的。
请斧正。
10.C#匿名函数的变量捕获(五章5.5)的更多相关文章
- js匿名函数(变量加括号就是函数)
js匿名函数(变量加括号就是函数) 一.总结 变量加括号就是函数,而函数的括号是用来传参的 1.类比:以正常函数去想匿名函数,匿名函数比正常函数只是少了函数名,本质还是一样,该怎么传参还是怎么传参,小 ...
- 【Go语言学习】匿名函数与闭包
前言 入坑 Go 语言已经大半年了,却没有写过一篇像样的技术文章,每次写一半就搁笔,然后就烂尾了. 几经思考,痛定思痛,决定金盆洗手,重新做人,哦不,重新开始写技术博文. 这段时间在研究Go语言闭包的 ...
- [Python Study Notes]匿名函数
Python 使用 lambda 来创建匿名函数. lambda这个名称来自于LISP,而LISP则是从lambda calculus(一种符号逻辑形式)取这个名称的.在Python中,lambda作 ...
- Python基础-列表推导式、匿名函数、os/sys/time/datetime/pymysql/xlwt/hashlib模块
列表推导式 [表达式 for 变量 in range(n) if 条件] 等效于 for 变量 in in range(n): if 条件: 表达式 优点:书写方便,缺点:不易读 注意:用的是方括号 ...
- Python进阶:函数式编程(高阶函数,map,reduce,filter,sorted,返回函数,匿名函数,偏函数)...啊啊啊
函数式编程 函数是Python内建支持的一种封装,我们通过把大段代码拆成函数,通过一层一层的函数调用,就可以把复杂任务分解成简单的任务,这种分解可以称之为面向过程的程序设计.函数就是面向过程的程序设计 ...
- js匿名函数和闭包总结
js匿名函数和闭包总结 一.总结 一句话总结:匿名函数的最主要作用是创建闭包,闭包就是将函数内部和函数外部连接起来的一座桥梁.内层的函数可以使用外层函数的所有变量,即使外层函数已经执行完毕.闭包可以用 ...
- (转)Python进阶:函数式编程(高阶函数,map,reduce,filter,sorted,返回函数,匿名函数,偏函数)
原文:https://www.cnblogs.com/chenwolong/p/reduce.html 函数式编程 函数是Python内建支持的一种封装,我们通过把大段代码拆成函数,通过一层一层的函数 ...
- 【scala】匿名函数和闭包
函数的类型和值 Scala是一种纯面向对象的语言,每个值都是对象.Java是一种不全面向对象的语言. Scala也是一种函数式语言,其函数也能当成值来使用.Java则是指令试编程. 但是Scala同时 ...
- matlab @(x)构造匿名函数
一起来学演化计算-matlab@(x)构造匿名函数 觉得有用的话,欢迎一起讨论相互学习~Follow Me 参考文献 https://www.ilovematlab.cn/thread-81614-1 ...
随机推荐
- KD Tree算法
参考:http://blog.csdn.net/v_july_v/article/details/8203674 #!/user/bin/env python # -*- coding:utf8 -* ...
- Storm calculate pv
本题其实就是storm的wordcout,需要把一个gz压缩的文件读取,并使用storm计算其pv. 样本 数据: 存储为accesslog.gz 我把它加载到我的虚拟机中/mnt/下. 没有使用tr ...
- Java 如何有效地避免OOM:善于利用软引用和弱引用
Java 如何有效地避免OOM:善于利用软引用和弱引用 想必很多朋友对OOM(OutOfMemory)这个错误不会陌生,而当遇到这种错误如何有效地解决这个问题呢?今天我们就来说一下如何利用软引用和弱引 ...
- Geoserver发布WMS服务出错分析
使用Geoserver发布一个空间表,在图层预览的过程中没有任何问题,但是当我根据这个空间表传创建视图再发布wms服务,访问时就会报错,错误信息如下: Caused by: java.sql.SQLE ...
- HFSS 边界条件
Ansoft HFSS求解就是对微分形式的麦克斯韦方程采取有限元方法进行数值求解,在场矢量和导数是都单值.有界而且沿空间连续分布的假设下,这些方程才可以使用.在边界和场 源处,场是不连续的,场的导数变 ...
- win8程序开机自启动管理
主要介绍利用系统自身的工具来管理开机自启动,而非第三方的工具,自己了解了,也写出来分享给大家@.·.@ 1.程序设置开机自启动 a. 打开计算机资源管理器-->进入"C:\Progra ...
- C# Reflection Type/MethodInfo
C#反射 在C#的反射中,可以通过Type来执行类中的某个方法,也可以通过MethodInfo来执行方法 三种调用方法 下面的示例中使用了三种方法来执行方法 两个类:Class1和Demo1,通过反射 ...
- NGUI 3.x 练习
一.常用快捷键 Alt+Shitf+W 创建一个新的 Widget Alt+Shift+S 创建一个新的 Sprite Alt+Shift+L 创建一个新的 Label Alt+Shift+T 创建一 ...
- 28Spring_的事务管理_银行转账业务加上事务控制_基于注解进行声明式事务管理
将applicationContext.xml 和 AccountServiceImpl 给备份一个取名为applicationContext2.xml 和 AccountServiceImpl2.j ...
- 课题:如何培养自己的SEO资源
课题:如何培养自己的SEO资源 问:做SEO最重要的是什么?[针对性的流量]答:看获取一样东西的门槛.稀缺性,人人可得价值不大外链 内容 流量[正确]针对性的自然流量是用户自愿带来的,价值高,能形成购 ...