C#中闭包的陷阱

C#也有闭包的概念:内层的函数可以引用包含在它外层的函数的变量,即使外层函数的执行已经完成(言下之意外部函数的局部变量应该被释放掉)。但该变量提供的值并非创建变量时的值,而是在父函数范围内执行的最终值。我们下面具体例子看看

复制代码
   static void Main()
   {
         Action[] act = new Action[6];
         for (var i = 0; i < act.Length; i++)
         {
             act[i] = () =>
             {
                string str = "dotnet开发跳槽" + i;
                Console.WriteLine(str);
             };
         }
         foreach (var item in act)
         {
            item();
         }
    }
复制代码

输出结果是

 

 是不是有点和你逾期的不一致,为啥?

产生的原因

因为在for循环中,只能有一个 i 变量。即在第一次循环时,i 的地址就分配好了,不会因为循环次数的多少而发生任何改变,其改变的只能是里面装载的值。当使用匿名方法时传进去的是变量的地址,不是具体值(传递的是引用)。只有当真正执行这个匿名方法时,才会去确定它的值。这就是为什么上面的例子中,其结果均为“dotnet开发跳槽6”。

怎么避免闭包陷阱

    在for循环中增加一个临时变量t,用来替换i,这时候每次循环编译器会对这个t重新分配内存,就不会出现这个问题了。代码如下:

复制代码

{
    Action[] act = new Action[6];
    for (var i = 0; i < act.Length; i++)
    {
        int t = i; //new 了一个临时变量
        act[i] = () =>
        {
            string str = "dotnet开发跳槽"+ t;
            Console.WriteLine(str);
        };
    }
    foreach (var item in act)
    {
        item();
    }
}
复制代码

闭包能让外部的局部变量的作用域延伸到匿名委托的生命周期内。

posted @   LearningAlbum  阅读(107)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示