iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >C#中怎么利用闭包捕获变量
  • 427
分享到

C#中怎么利用闭包捕获变量

2023-06-17 13:06:40 427人浏览 泡泡鱼
摘要

C#中怎么利用闭包捕获变量,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。简单来讲,闭包允许你将一些行为封装,将它像一个对象一样传来递去,而且它依然能够访问到原来

C#中怎么利用闭包捕获变量,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。

简单来讲,闭包允许你将一些行为封装,将它像一个对象一样传来递去,而且它依然能够访问到原来***次声明时的上下文。这样可以使控制结构、逻辑操作等从调用细节中分离出来。访问原来上下文的能力是闭包区别一般对象的重要特征,尽管在实现上只是多了一些编译器技巧。

我们知道,在匿名方法或者lambda中,可以访问或者修改该匿的定义范围内的变量。例如:

int num = 1;   Func<int> incNum = () => ++num;

其中lambda表达式使用了在其外部定义的变量num。我们可以认为该段lambda语句块构成了一个闭包,而这个闭包捕获了外部变量num。

好了,不说那么多让人看着难受的定义套话了。我们进入正题,看看在C#中变量是如何被捕获的。来看一个例子:

public Func<String> CreateFunction()   {   String str = "我的幸运数字是";   int num = 17;   Func<String> func = () => str + num;   return func;   }

在这个例子中,定义了一个返回一个函数的方法CreateFunction。返回的函数构成了一个闭包,该闭包捕获了两个变量:String类型的str和int类型的num。

好了,我们现在可以这样使用这个函数了:

Func<String>   myFunc = CreateFunction();   String result = myFunc();

我们来分析一下这两行代码实际都干了什么。***行很容易理解,我们把方法CreateFunction生成的匿名函数赋值给了委托myFunc。

第二行更好理解,我们执行了myFunc,并将返回结果赋值给了变量result。我们再深入思考一下:在执行myFunc的时候,会访问到在CreateFunction中定义两个变量str与num。

虽然这时CreateFunction的栈帧早就被销毁了,其内部定义的变量至今也“生死不明”了,但是因为我们知道这两个变量已经被闭包所捕获了,所以我们坚信这两个变量截至目前为止还是可以访问的!

对于str对象,鉴于它是一个引用类型,所以只要有存在某个“东西”一直保存着对它的引用,它就不会被销毁。这样我们完全不用担心在我们需要它时,编译器或运行时会告诉我们它被弄丢了。

然而对于num,情况就有些不同了。num是一个值类型。我们知道值类型是存活在栈上的,我们也知道它所存在的那个栈帧(也就是CreateFunction的帧)在CreateFunction执行完毕后就会被销毁,然后其上存在的任何值类型也会被一并的销毁,这其中当然包括我们所关注的变量num了。

那么,我们为什么还能安全的访问num呢?C#中的变量捕获机制究竟有什么神奇之处,可以让值类型拥有违反常规的生存周期呢?装箱!你可能会立刻想到,把每个值类型都装到一个对象里,我们就可以让这个值类型拥有和那个包裹它的对象相同的寿命了。

不过,这并不是C#实现者所选择的方式!C#并不会对每个需要捕获的值类型变量进行装箱操作,而是把所有捕获的变量统统放到同一个大“箱子”里&mdash;&mdash;当编译器遇到需要变量捕获的情况时,它会默默地在后台构造一个类型,这个类型包含了每一个闭包所捕获的变量(包括值类型变量和引用类型变量)作为它的一个公有字段。这样,编译器就可以

维护那些在匿名函数或lambda表达式中出现的外部变量了。

更进一步,如果我们使用ILDASM工具查看CreateFunction方法的IL代码,我们会发现编译器压根就没有声明num和str变量。取而代之的是声明了一个类型名和实例名都及其难看的包装对象。这个玩意儿就是我们上面所说的那个被编译器默默生成,保存了所有捕获变量的引用的对象。

我们还可以看到,在CreateFunction方法,C#源代码内所有对str和num的操作,在IL中都被转换成了对包装对象的同名公有成员的操作。顺便说一句,就连我们构造的那个lambda表达式“() => str + num”现在都被编译器转换成了这个包装对象的一个方法!

看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注编程网精选频道,感谢您对编程网的支持。

--结束END--

本文标题: C#中怎么利用闭包捕获变量

本文链接: https://www.lsjlt.com/news/289207.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C#中怎么利用闭包捕获变量
    C#中怎么利用闭包捕获变量,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。简单来讲,闭包允许你将一些行为封装,将它像一个对象一样传来递去,而且它依然能够访问到原来...
    99+
    2023-06-17
  • 利用FORCE_MATCHING_SIGNATURE捕获非绑定变量SQL
    sql text 相近的sql FORCE_MATCHING_SIGNATURE 相同 因此可以使用下面的语句查找没有绑定变量的SQL SELECT *  &...
    99+
    2024-04-02
  • 如何使用golang函数闭包捕捉变量
    如何使用 go 函数闭包捕获变量?定义一个包含要捕获变量的函数参数。在函数体内,使用捕获的变量。示例:计数器闭包缓存闭包闭包在 go 中用于捕获变量并创建灵活和可重用的代码。 如何使用...
    99+
    2024-04-23
    golang 闭包
  • mysql中怎么利用sniffer捕获SQL语句
    这篇文章给大家介绍mysql中怎么利用sniffer捕获SQL语句,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。MySQL5.1之前general log不能在运行时启用或禁用,有时想...
    99+
    2024-04-02
  • node.js中怎么利用express捕获全局异常
    这期内容当中小编将会给大家带来有关node.js中怎么利用express捕获全局异常,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。场景express的路由里抛出异常后,全...
    99+
    2024-04-02
  • 详细聊聊如何在C#循环中捕获局部变量
    目录问题:解答方案:总结问题: 我遇到了一个有趣的问题,它的代码大概是这样的。 List<Func<int>> actions = new List&l...
    99+
    2024-04-02
  • 怎么在javascript中捕获窗口关闭事件
    本篇文章给大家分享的是有关怎么在javascript中捕获窗口关闭事件,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。JavaScript的作用是什么1、能够嵌入动态文本于HTM...
    99+
    2023-06-14
  • python 闭包中引用的变量值变更问题
    python的闭包当内层函数引用外层函数的局部变量时,要正确使用闭包,就要确保引用的局部变量在函数返回后不能变。如下:def count():     fs = []     for i in range(1, 4):         de...
    99+
    2023-01-31
    包中 变量值 python
  • Shell eval怎么用变量获取环境变量
    这篇文章主要讲解了“Shell eval怎么用变量获取环境变量”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Shell eval怎么用变量获取环境变量”吧!场景系统中存在环境变量 USER=...
    99+
    2023-06-09
  • 利用Ajax技术获取PHP方法中的变量
    利用Ajax技术获取PHP方法中的变量 随着Web应用程序的不断发展,Ajax技术逐渐成为Web开发中不可或缺的重要组成部分。Ajax技术可以使用户与服务器之间的交互更加流畅和高效,同...
    99+
    2024-03-09
    变量 php ajax php脚本
  • C#中怎么利用WMI获取数据
    本篇文章给大家分享的是有关C#中怎么利用WMI获取数据,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。 首先启动Visual Studio .Net,依次选择"文件&q...
    99+
    2023-06-17
  • C++ 函数中的 lambda 表达式如何通过参数传递捕获外部变量?
    c++++ lambda 表达式可以通过参数传递来捕获外部变量,具体步骤如下:定义一个接受 lambda 表达式作为参数的函数。在 lambda 表达式中捕获外部变量。将 lambda ...
    99+
    2024-04-25
    lambda 捕获外部变量 c++
  • PHP中怎么利用ini_get_all函数获取设置选项变量介绍
    这篇文章将为大家详细讲解有关PHP中怎么利用ini_get_all函数获取设置选项变量介绍,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。把所有选项值以数组的形式返回,方便你当phpinfo(...
    99+
    2023-06-17
  • 怎么掌握js作用域链、内存回收、变量、闭包
    本篇内容介绍了“怎么掌握js作用域链、内存回收、变量、闭包”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一...
    99+
    2024-04-02
  • VB.NET中怎么获取环境变量
    本篇文章为大家展示了VB.NET中怎么获取环境变量,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。Windows系统将很多重要的信息(比如计算机名和用户名)存储在环境变量中。访问这些变量来获取这些信息...
    99+
    2023-06-17
  • C++项目中怎么实现闭包
    今天就跟大家聊聊有关C++项目中怎么实现闭包,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。示例#include <iostream>#include ...
    99+
    2023-06-19
  • Javascript中怎么利用闭包循环绑定事件
    Javascript中怎么利用闭包循环绑定事件,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。例如:一个不确定长度的列表,在鼠标...
    99+
    2024-04-02
  • vue data中怎么获取使用store中的变量
    这篇文章主要讲解了“vue data中怎么获取使用store中的变量”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“vue data中怎么获取使用store中的变量”吧!d...
    99+
    2023-06-29
  • Python编程中闭包的变量作用域问题解析
    目录闭包闭包中的变量闭包 ​ 在我们使用返回函数的时候,由于我们在一个函数中需要返回另一个函数,因此,我们在这个函数中就需要重新定义一个函数。而这样,就造成了我们的函数嵌...
    99+
    2024-04-02
  • JavaScript中闭包怎么用
    这篇文章将为大家详细讲解有关JavaScript中闭包怎么用,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。闭包真的是学过一遍又一遍,Js博大精深,每次学习都感觉有新的收获...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作