在Lambda表达式中使用循环变量

在C#5.0之前的版本中,如果在foreach循环中的lambda使用循环变量,那么你会发现一些意想不到的现象,例子如下:

            var integers = new List<int> { 1, 2, 3, 4 };
            var actions = new List<Action>();
            foreach (var integer in integers)
            {
                actions.Add(() => Console.WriteLine(integer));
            }
            actions.ForEach(action => action());

这段代码的输出不是所期望的
1

2

3

4

而是

4

4

4

4

原因是actions里的lambda表达式捕获的循环变量被覆盖了,而循环变量的最后一个值是4. 解决方法是引入一个局部变量让lambda表达式捕获或者使用Foreach扩展函数:

            var action1s = new List<Action>();
            foreach (var integer in integers)
            {
                var tmpInt = integer;
                action1s.Add(() => Console.WriteLine(tmpInt));
            }
            action1s.ForEach(action => action());
            var action2s = new List<Action>();
            integers.ForEach(interger => action2s.Add(() => Console.WriteLine(interger)));
            action2s.ForEach(action => action());

完整的例子代码和输出结果如图:

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("foreach (var integer in integers)");
            var integers = new List<int> { 1, 2, 3, 4 };
            var actions = new List<Action>();
            foreach (var integer in integers)
            {
                actions.Add(() => Console.WriteLine(integer));
            }
            actions.ForEach(action => action());

            Console.WriteLine("foreach (var integer in integers) with local variable");
            var action1s = new List<Action>();
            foreach (var integer in integers)
            {
                var tmpInt = integer;
                action1s.Add(() => Console.WriteLine(tmpInt));
            }
            action1s.ForEach(action => action());

            Console.WriteLine("use ForEach extension method");
            var action2s = new List<Action>();
            integers.ForEach(interger => action2s.Add(() => Console.WriteLine(interger)));
            action2s.ForEach(action => action());
            Console.WriteLine("done");
            Console.Read();
        }
    }

在C#5.0中这个行为得到了纠正,下图是同样程序的运行结果:

时间: 2024-12-28 12:46:12

在Lambda表达式中使用循环变量的相关文章

boost在lambda表达式中调用占位符参数的成员函数的方法

boost中提供了lambda表达式的用法,但是lambda表达式的功能还不是很强大,在其中只能对lambda的占位符参数_1等使用最基本的操作符,如+-*/,可是很多时候如果传入的占位符参数是一个对象指针的话,我们可能想要调用这个类的成员函数. 我在开发中遇到了这个问题,需要在stl的算法中传入一个函数来调用对象的比较函数,因为感觉这样太麻烦,还需要重新定义一个函数,所以想起了lambda表达式,c++11的lambda表达式我倒是没试过,可是受项目开发环境所限,只能选择boost.但是我用的

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>>(); f

Lambda表达式中的表达式lambda和语句lambda区别

Lambda表达式可分为表达式lambda和语句lambda 表达式lambda:表达式位于 => 运算符右侧的lambda表达式称为表达式lambda (input parameters) => expression //表达式lambda 例如 (x, y) => x == y 语句lambda:=> 运算符右侧是一个语句块,语句包含在大括号中 (input parameters) => {statement;} //语句lambda 例如: (x, y) => {

(转) Lambda表达式中的表达式lambda和语句lambda区别

Lambda表达式可分为表达式lambda和语句lambda 表达式lambda:表达式位于 => 运算符右侧的lambda表达式称为表达式lambda (input parameters) => expression //表达式lambda 例如 (x, y) => x == y 语句lambda:=> 运算符右侧是一个语句块,语句包含在大括号中 (input parameters) => {statement;} //语句lambda 例如: (x, y) => {

Javascript中的循环变量声明,到底应该放在哪儿?

不放走任何一个细节.相信很多Javascript开发者都在声明循环变量时犹豫过var i到底应该放在哪里:放在不同的位置会对程序的运行产生怎样的影响?哪一种方式符合Javascript的语言规范?哪一种方式和ecma标准未来的发展方向匹配?本文将对四种常见的声明循环变量的书写方式进行简单的分析和比较. 习惯1:不声明直接使用 function loop(arr) { for (i = 0; i < arr.length; i++) { // do something } } 非常危险的使用习惯,

lambda表达式中的空指针问题

今天看demo环境阿里云的日志,发现有报空指针,既然这样那就解决一下呗. 报错代码如下. 很显然 shipment为空 调用处的代码如下 突然发现气氛陷入了尴尬的沉默.如果说shipments为空的话,lambda表达式是不会进行的.那么这个空指针是从哪里来的呢? 再跟一下. 调用处在这里. 那么我们可以猜一下,应该是shipments本身不为空,但是里面的元素为null. 试了一下,果然OK了. 原文地址:https://www.cnblogs.com/tyoutetu/p/11498498.

python中for循环中的循环变量

废话不多说,代码伺候: for i in range(3): print("hello") print(i) 运行结果如下: 从上面的例子可以看出,for循环里面的循环变量i作用域衍生到循环外面了.说明循环变量i,在遍历完之后值并没有消失,而是保留了最后一个变量的值,而且会覆盖之前变量的值!所以平时在使用的时候变量最好别和模块其他变量重复,否则可能出问题! 原文地址:https://www.cnblogs.com/xiaohaodeboke/p/12128829.html

lambda表达式中的Select和Where的区别?

Select()操作符:可以将序列中的每个元素投影到新表中,即取出哪些属性(字段),其实和sql中的select差不多的意思. Where()操作符:是用于对序列中的元素进行过滤和筛选,类似sql中是where字句 例如: 注意:Select()对每一条数据进行投影到一张新的表中 new {p.Name}  使用了匿名类,该匿名类中只包含原表中的Name字段,相当与取Name字段,和sql中的select查询一样 总结:Where()操作符是用于过滤用的,和sql中的where字句一样. 那如果

用lambda表达式替代 for循环进行批量操作。

IEnumerable<Rect> rectlist3 = rectlist.Select(rect =>newRect(rect.X + 2000, rect.Y, rect.rect.Width, rect.rect.Height));