• 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也是同样的道理

  • 相关阅读:
    ATOMac
    基于Python3 + appium的Ui自动化测试框架
    记 被难到的第一个算法题
    Requests发Post请求data里面嵌套字典
    Struts,Sping和Spirng MVC等框架分析
    雷军的留名,不是以程序员身份
    你有考虑过如果不做程序员,你会从事什么职业吗?或者你现在正在发展什么第二职业?
    java中的运算运算符 与或非(转)
    记录常用函数
    SQLServer记录常用函数(转)
  • 原文地址:https://www.cnblogs.com/sheseido/p/9893523.html
Copyright © 2020-2023  润新知