文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

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

2023-06-17 13:16

关注

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”现在都被编译器转换成了这个包装对象的一个方法!

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

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯