10.C#匿名函数的变量捕获(五章5.5)

小分享:我有几张阿里云优惠券,用券购买或者升级阿里云相应产品最多可以优惠五折!领券地址:https://promotion.aliyun.com/ntms/act/ambassador/sharetouser.html?userCode=ohmepe03



  首先感谢园友的指定,后续的文章一定会多码多想,出来的文章才有说服力。那今天接上篇我们来聊一聊匿名函数,对于匿名函数,我们知道使用delegate关键字,那我们来需要知道匿名函数在变量是的处理方式,先说两个术语,外部变量和捕获的外部变量,可以看出"捕获的外部变量=外部变量+捕获了",这个捕获顾名思义就是在匿名函数中使用了这个变量。

  外部变量:指在一个包含匿名方法的作用域内的变量或者参数,在类的实例成员内部的匿名方法,this也是认为是一个外部变量。

  捕获的外部变量:它是指在匿名方法中使用的外部变量。

  代码如下

 1 static void Main(string[] args)
 2 {
 3     //x和y称为外部变量
 4     int x = 0, y = 1;
 5     //在匿名方法中使用到了x,则x称为捕获的外部变量
 6     Action<int> ac = delegate (int n) { Console.WriteLine(x); };
 7
 8     //小结:x、y和匿名方法都在Main函数的作用域内,也可以扩展到类的作用域及命名空间的作用域
 9
10     Console.ReadKey();
11 }

  再来说下匿名方法捕获变量的行为,可以看到在匿名方法中我们访问到了局部变量x,请注意,并不是仅仅访问到了x的值,而是在匿名类型中使用一个类型实例引用到了变量x,对于x的改变,因为是引用,所以总能使用这个类型实例访问到,如

1 long x1 = 11, y1 = 12;
2 Action<long> ac1 = delegate (long l) { Console.WriteLine(x1); };
3 ac1(1L); //打印11
4 x1 = y1;
5 ac1(1L);  //打印12

  参数long l这里没有使用到,不过这里的参数不是上面所说的外部变量,因为它确实是匿名方法的参数

1 static void Debug(int x) {
2     Action<int> a = delegate (int y) { Console.WriteLine(x); };
3 }

  上面的x就是术语中说的外部变量,分清定义就应该没问题了吧。

  关于变量的生存周期,可以就只在一个作用域内,当代码执行完这个作用域,该作用域内的变量也会被销毁,但使用匿名方法可以延长变量的生存周期。

 1 static void Main(string[] args)
 2 {
 3     GetLen gl = GetMethod();
 4     gl("s"); //打印00s
 5     gl("s"); //打印0000s
 6
 7     Console.ReadKey();
 8 }
 9
10 public delegate int GetLen(string s);
11 static GetLen GetMethod()
12 {
13     string temp = "0";
14     return delegate (string s) {
15         temp = String.Concat(temp, temp);
16         s = String.Concat(temp, s);
17         Console.WriteLine(s);
18         return s.Length;
19     };
20 }

  看出使用GetMethod返回一个委托,这里使用匿名函数(因为匿名函数就是对应签名的委托),在正常理解下temp在GetMethod作用域内,当离开作用域外,这个变量会销毁,但说过匿名函数会使用一个类型实例引用这个变量,则这个变量不会销毁,只有当匿名函数销毁(也就是委托)才会跟着销毁,从而延长了变量的作用域,而且对于temp变量的操作也会直接反应在实例引用的变量上,如第一次调用gl("s"),temp="00",第二次调用时,temp="0000"。

   最后说下有点绕的东西,就是变量的实例化在匿名函数中的访问规则,不过个人感觉这个还真是不很绕,还算是比较好理解的。看下代码。

 1 GetLen[] a = { };
 2 int xx = 0;
 3 for (int i = 0; i < 3; i++)
 4 {
 5     int xxx = i;
 6     a[i] = delegate (string s) {
 7         xx++;
 8         xxx++;
 9         return xx + xxx;
10     };
11 }

  a是一个委托数组,对于数组中每一个委托都共享一个xx实例引用,而每一个委托都各自拥有一个xxx实例引用(xxx对应不同的委托是不同的),这是因为在循环中,每一次的循环都实例化了xxx,则对于各个委托都有一个全新的xxx实例引用,而xx则是在循环之外实例化的,则每个委托共享一个实例引用。当然在实际的使用过程中,不可能那么简单,那么要我们开动大脑,好好区别哪一个共享的,哪一个是独自引用的。

  请斧正。

参考页面:http://qingqingquege.cnblogs.com/p/5933752.html

时间: 2024-11-10 08:06:08

10.C#匿名函数的变量捕获(五章5.5)的相关文章

HTML代码中在两个匿名函数中使用同名变量出现bug而引起的变量作用域的思考

在学习HTML的时候,为了方便地对同一个css样式的不同值的效果进行对比,我做成了下面这个样子. 代码也是很典型的用于展示的格式(p元素的内容随便写的): 1 <head> 2 <style> 3 p{ 4 border: medium solid black; 5 padding: 5px; 6 margin: 5px; 7 text-justify:inter-word; 8 } 9 button{ 10 margin: 5px; 11 } 12 </style>

python协程函数、递归、匿名函数与内置函数使用、模块与包

目录: 协程函数(yield生成器用法二) 面向过程编程 递归 匿名函数与内置函数的使用 模块 包 常用标准模块之re(正则表达式) 一.协程函数(yield生成器用法二) 1.生成器的语句形式 a.生成器相关python函数.装饰器.迭代器.生成器,我们是如何使用生成器的.一个生成器能暂停执行并返回一个中间的结果这就是 yield 语句的功能 : 返回一个中间值给调用者并暂停执行. 我们的调用方式为yeild 1的方式,此方式又称为生成器的语句形式. 而使用生成器的场景:使用生成器最好的场景就

Python进阶:函数式编程(高阶函数,map,reduce,filter,sorted,返回函数,匿名函数,偏函数)...啊啊啊

函数式编程 函数是Python内建支持的一种封装,我们通过把大段代码拆成函数,通过一层一层的函数调用,就可以把复杂任务分解成简单的任务,这种分解可以称之为面向过程的程序设计.函数就是面向过程的程序设计的基本单元. 而函数式编程(请注意多了一个"式"字)--Functional Programming,虽然也可以归结到面向过程的程序设计,但其思想更接近数学计算. 我们首先要搞明白计算机(Computer)和计算(Compute)的概念. 在计算机的层次上,CPU执行的是加减乘除的指令代码

09 匿名函数、函数作用域、闭包、递归

匿名函数(lambda) 语法规则: lambda 参数:表达式 filter(lambdax: x>10, li) 匿名函数:可以赋给一个变量,重复使用. fun1 = lambda x: x * 10 print(fun1(10)) 打印结果: 100 fun = (lambda x: x * 10)(5) print(fun) 打印结果: 50 函数作用域 01外部不能访问函数内部变量: def fun1(): x = 1 print(x) 02函数内部能够访问函数外部变量: x = 12

js 匿名函数 用法

JS执行顺序为从上到下 先声明存储匿名函数的变量放在JS文件中 <script src="/Scripts/niming.js" type="text/javascript"></script> var dononamefuc = function (p) { return '操作' + p; } 也可以重写匿名函数方法体 dononamefuc = function (p) { return '重写操作' + p; } 以下为调用页面执行逻

Python 之匿名函数和偏函数

匿名函数与偏函数 匿名函数 Python允许使用lambda关键字创造匿名函数,lambda表达式用于定义匿名函数,它返回可调用的函数对象,语法如下: lambda arg1, arg2, … : expression例如: add = lambda a,b=2 : a+b print(add(3)) # 5 print(add(3, 10)) # 13 匿名函数具有比较浓郁的函数式编程风格,例如: foo = [2, 18, 9, 22, 17, 24, 8, 12, 27] print fi

javascript中的匿名函数整理笔记

以下为总结在开源的JavaScript框架中能看到很多这样语法结构(function(){})()比如我最近看的jQuery,及chediter.刚开始的时候我看到这样的结果有点奇怪,它是怎么执行的,并且这是什么样的语法结构,最近偶尔看闭包的时候,才发现原来这是JavaScript种匿名函数(看到这个有点汗,java的匿名类见过,就从来没想到JavaScript中会有匿名函数,也是学的不够牢固).现在我们了解到以上是JavaScript匿名函数的语法结构,怎么声明函数,匿名函数JavaScrip

Python学习笔记__4.3章 匿名函数(简洁函数)

# 这是学习廖雪峰老师python教程的学习笔记 1.概览 关键字lambda表示匿名函数 list(map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9])) # 列表生成式中的 lambda 实际就是 def f(x): return x * x 但匿名函数有个限制,就是只能有一个表达式. 匿名函数不用写return,返回值就是该表达式的结果 匿名函数因为函数没有名字,不必担心函数名冲突. 此外,匿名函数也是一个函数对象,可以把匿名函数赋值给一个变量

067-PHP使用匿名函数

<?php $func=function ($x,$y){ //匿名函数与变量绑定 return $x+$y; }; echo '5+6='.$func(5,6); //使用匿名函数 echo '<br />15+16='.$func(15,16); ?> 原文地址:https://www.cnblogs.com/tianpan2019/p/10995324.html