`

C# foreach lambda breaks with closure

    博客分类:
  • C#
阅读更多

Let first take a prediction,  what is the result of the following code. 

 

 

 

public static void ClosureForeachWithLambda()
    {
      var action = new List<Action>();
      var list = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
      foreach (var i in list)
      {
        action.Add(() => Console.WriteLine(i));
      }

      foreach (var i in action)
      {
        i();
      }

    }

 

 

It is not 1..9 printed each once, instead it is the 9 printed 9 times. Not belieing, huh, trying it yourself.

 

 

So, let me post a complete code with comments to tell why this is happening.  Also, in my code below, you will see a fix to the bug in .net 4. 0 

 

 

 

public static void Main(string[] args)
    {

      ClosureForeachWithLambdaGotha();
    }



    public static void ClosureForeachWithLambda()
    {
      // the reason why this is a potential pitfall is because 
      // closure is not creating a copy, not copying the value, but instead it is 
      // the variable itself.
      // but inside theo foreach loop, 
      // it is loop variable that is bound to and the bound is updated in each loop
      // so at last, you will see that it is '9' that is printed 9 times
      var action = new List<Action>();
      var list = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
      foreach (var i in list)
      {
        action.Add(() => Console.WriteLine(i));
      }

      foreach (var i in action)
      {
        i();
      }

    }

    public static void ClosureForeachWithLambdaGotha()
    {
      // a fix is to explicitly create a local variable, 
      // by which it is the variable in new scope that is closured
      // here shows how:
      //
      // fortunately thi is going to be fixed in .net 4.5
      // however, the bad news is that since 4.5 is going to be a inplace change. 
      // so that means it is going to be a breaking change.
      var action = new List<Action>();
      var list = new [] { 1,2 ,3, 4, 5, 6, 7, 8, 9};
      foreach (var i in list)
      {
        var copy = i;
        action.Add(() => Console.WriteLine(copy));
      }

      foreach (var i in action)
	    {
        i();
	    }
    }
 

 

As explained in the post  : Lifting Foreach, Breaking change in Visual Studio 2012. It is going to be a breaking change, as the .net 4.5 is going to be a in place patch .

 

分享到:
评论

相关推荐

    c#Foreach.rar

    在C#编程语言中,`foreach`循环是一个非常重要的控制流结构,用于遍历集合、数组或枚举类型的元素。这个`c#Foreach.rar`压缩包包含了一个名为`foreach.txt`的文本文件,很可能是对`foreach`用法的简要说明。在这里,...

    c#中Foreach详细用法

    C#中Foreach详细用法 Foreach语句是C#语言中的一种循环语句,它提供了一个简洁高效的方式来遍历数组、集合、列表等数据结构。在本文中,我们将详细介绍Foreach语句的用法和优点,并与传统的for循环语句进行比较。 ...

    C# Lambda表达式示例

    Lambda表达式是C#编程语言中的一个重要特性,它在处理函数式编程和LINQ查询时尤其有用。Lambda表达式提供了一种简洁的方式来定义匿名函数,使得代码更加紧凑和易读。下面我们将深入探讨C# Lambda表达式的概念、语法...

    C#在foreach遍历删除集合中元素的三种实现方法

    在foreach中删除元素时,每一次删除都会导致集合的大小和元素索引值发生变化,从而导致在foreach中删除元素时会抛出异常。 集合已修改;可能无法执行枚举操作。 方法一:采用for循环,并且从尾到头遍历 如果...

    C# Foreach用法

    Csharp Foreach用法 可以对比for的区别

    C#并发实战记录之Parallel.ForEach使用

    C#并发实战记录之Parallel.ForEach使用 本篇文章主要介绍了C#并发实战记录之Parallel.ForEach使用的相关知识点。通过示例代码,详细介绍了Parallel.ForEach的使用方法和优化技巧。 一、使用Parallel.ForEach优化...

    java8lambda表达式Demo

    Java 8 是一个重要的Java平台版本,因为它引入了许多新特性,其中最显著的就是Lambda表达式。Lambda表达式是函数式编程的关键元素,它允许我们以更简洁、更易读的方式编写代码,特别是在处理集合和并发任务时。在这...

    C#使用Lambda语句通过EF操作数据库

    Lambda表达式是C#中的一个功能强大的特性,常用于简化代码,特别是在LINQ(Language Integrated Query)查询中。本篇文章将深入探讨如何利用C#中的Lambda表达式和EF框架来操作SQL数据库。 首先,要使用EF,你需要在...

    C#foreach用法案例,使用VS2019编写

    在C#编程语言中,`foreach`循环是一种用于遍历集合、数组或其他可迭代对象的便利语法。在本文中,我们将深入探讨`foreach`循环的工作原理、如何使用它以及一些实用案例,这些案例都是在Visual Studio 2019环境下编写...

    C# foreach最好的源码foreach测试.rar

    在C#编程语言中,`foreach`循环是一个非常重要的语法结构,它用于遍历集合、数组或其他可迭代对象中的元素。这个压缩包文件"foreach测试.rar"可能包含了一些示例代码,用于展示`foreach`循环的工作原理和最佳实践。...

    C#中foreach循环对比for循环的优势和劣势

    本文将详细给大家关于C#中foreach循环对比for循环的优势和劣势,下面话不多说了,来一起看看详细的介绍吧。 一、foreach循环的优势 C#支持foreach关键字,foreach在处理集合和数组相对于for存在以下几个优势: 1、...

    C#foreach原理

    C# foreach原理 foreach语句是C#中用于遍历数组、集合或其他实现了IEnumerable接口的数据结构的一种便捷方式。在C#中,foreach语句隐藏了迭代器的复杂性,让开发者可以轻松地对集合中的每个元素执行操作,而无需...

    Parallel.ForEach的卡死现象(线程操作问题C#源码实例)

    在.NET编程环境中,`Parallel.ForEach`是一个非常有用的并行处理工具,它允许开发者将数据集中的每个元素在多个线程上并行处理,以提高应用程序的执行效率。然而,正如标题所指出的,`Parallel.ForEach`可能会遇到...

    C#中foreach语句使用break暂停遍历的方法

    在C#编程语言中,`foreach`语句用于遍历集合、数组或其他可迭代对象中的元素,这在处理数据集合时非常常见。然而,在某些情况下,我们可能希望在遍历过程中提前终止循环,这时就可以使用`break`语句。本文将深入探讨...

    C#中foreach实现原理详解

    C#中foreach实现原理详解 C#中foreach的实现原理是基于可枚举类型和枚举器的概念。可枚举类型是指实现了IEnumerable接口的类,例如List、ArrayList等。这些类都可以用foreach进行遍历。 在C#中,foreach语句的执行...

    for foreach效率测试代码

    `for` 和 `foreach` 循环在C#中被广泛使用,它们各自有特定的用途和效率特点。本篇将深入探讨这两种循环结构,以及它们在执行大量遍历操作时的性能差异。 `for` 循环是一种灵活的循环结构,适用于需要知道循环次数...

    For 和 Foreach 的效率问题

    本文将深入探讨`for`和`foreach`在C#中的效率差异,以及如何根据具体场景选择合适的循环方式。 首先,`for`循环是一种更基础的迭代结构,它允许程序员直接控制循环变量的初始化、条件检查和递增/递减过程。`for`...

    深入理解C#中foreach遍历的使用方法

    C#中的`foreach`遍历是编程中常用的操作,它简化了对集合、数组和列表等数据结构的迭代。在C#中,`foreach`循环主要用于遍历实现了`IEnumerable`接口的对象,包括数组、列表(`List&lt;T&gt;`)、字典(`Dictionary, ...

    数据结构 C#版 链表 加强版 支持 foreach语句

    本文将详细讲解C#中链表的实现,并特别关注加强版链表,它支持了C#语言的`foreach`语句进行遍历。这对于初学者来说是一个很好的实践案例。 链表是一种线性数据结构,不同于数组,它的元素不是在内存中连续存储的。...

Global site tag (gtag.js) - Google Analytics