Lambda表达式和For循环使用需要注意的一个地方

一个需要注意的地方
看下面的代码:

复制代码

using System;
using System.Collections.Generic;
using System.Linq;

namespace MyCsStudy
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Func<int>> list = new List<Func<int>>();

            for (int i = 0; i < 3; i++)
            {
                list.Add(() => i); //list依次添加0,1,2??
            }
            foreach (var item in list)
            {
                Console.WriteLine(item()); //输出的竟然是?
            }
        }
    }
}
复制代码

运行试一下看看结果,如果你以前碰到过js里的闭包问题,相信你不会大惊小怪(而且可能已经知道了问题的原因),但是,如果你从来没有碰到过这种情况,是不是令你大吃一惊?!输出的竟然不是0,1,2,而是三个3,oh,my god。紧接着,立刻,你会大胆想到这里的list在Add方法执行的地方Add进去的是一个引用类型(这里是lambda表达式()=>i),它们执行的结果共同指向值为3的同一个引用地址!
没错,我们详细分析一下:
1、我们首先定义一个list,其存储格式为func<int>,即返回int型的代理;然后,用for循环将i封装进lambda表达式,并加入到该list中,最后,用foreach循环输出结果。
2、因为lambda表达式实质就是个委托,也就指向一个匿名函数,所以,在foreach输出的时候,使用item()来调用它,让它所指向的函数执行。
至于第2步中item()执行的结果为什么都是3,原因是这样的:
(1)在for循环中,只能有一个 i 变量。即在第一次循环时,i 的地址就分配好了(注意了,这里i的地址第一次分配后是不变的),不会因为循环次数的多少而发生任何改变,其改变的只能是里面装载的值。
(2)lambda表达式在构造时, 传进去的是变量的地址,而不是具体值。只有当真正执行这个lambda表达式时,才会去确定它的值。这就是为什么上面的例子中,其结果均为3(for循环在最后,当i=2时,i又加了1)。

那么如何解决这个问题?解决方案很简单:

1是在for循环中,定义一临时变量tmpNum,存储i的值即可。因为编译器会对该临时变量重新分配内存,这样,每次循环,都重新分配新的内存,就不会有这个问题了。

2用foreach也是同样的道理

posted @   老皮肉  阅读(4872)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
历史上的今天:
2011-11-02 ie6 几个li上下排列会闪动的问题,嵌套div—外层div内层div都设置背景颜色,内层div背景色不显示的问题
点击右上角即可分享
微信分享提示