如何在C#中绑定的lambda到一个foreach枚举? [英] How does a lambda in C# bind to the enumerator in a foreach?

查看:1263
本文介绍了如何在C#中绑定的lambda到一个foreach枚举?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我只是碰到的最意外的行为来。我敢肯定有它的工作这样一个很好的理由。谁能帮解释一下吗?

I just came across the most unexpected behavior. I'm sure there is a good reason it works this way. Can someone help explain this?

考虑这个code:

var nums = new int[] { 1, 2, 3, 4 };
var actions = new List<Func<int>>();

foreach (var num in nums)
{
    actions.Add(() => num);
}

foreach (var num in nums)
{
    var x = num;
    actions.Add(() => x);
}

foreach (var action in actions)
{
    Debug.Write(action() + " ");
}

输出对我来说是有点出人意料:

The output is a bit surprising for me:

4 4 4 4 1 2 3 4 

显然有什么东西与拉姆达是如何引用枚举回事。在fo​​reach的第一个版本,是民实际上必然要当前,而不是由它返回的结果?

Obviously there's something going on with how the lambda is referencing the enumerator. In the first version of the foreach, is 'num' actually bound to 'Current', instead of the result returned by it?

推荐答案

这是众所周知的,并建立有关lambda表达式的行为,虽然经常令人惊讶那些已经遇到过的第一次谁。最根本的问题是,你有什么拉姆达的心理模型的的说法并不正确。

This is well-known and established behavior regarding lambdas, though frequently surprising to those who've encountered it for the first time. The fundamental issue is that your mental model of what a lambda is isn't quite correct.

一个拉姆达是,直到它的调用不得到运行的功能。你封一个结合参照该拉姆达实例,而不是价值。当你在最后的foreach循环执行你的行动,这就是你真正跟随封闭参考看看它是什么第一次。

A lambda is a function that doesn't get run until it's invoked. Your closure binds a reference to that lambda instance, not the value. When you execute your actions in your final foreach loop, that's the first time you're actually following the closed reference to see what it is.

在第一种情况下,你引用次数,并在这一点上,num的值是4,所以当然所有的输出4.在第二种情况下,每个拉姆达已经绑定到不同的值,是本地的每一次循环,而且值不会改变(尚未GC'd的仅仅是因为拉姆达参考。)因此,你会得到您所期望的答案。

In the first case, you're referencing num, and at that point, the value of num is 4, so of course all your output is 4. In the second case, each lambda has been bound to a different value that was local to the loop each time, and that value isn't changed (it hasn't been GC'd solely because of the lambda reference.) therefore, you get the answer that you expect.

在本地临时值的盖实际上是捕获从一个点的特定值在时间上的λ内的标准方法

The closure over a local temporary value is actually the standard approach to capture a specific value from a point in time within the lambda.

亚当的<一个href=\"http://blogs.msdn.com/ericlippert/archive/2009/11/12/closing-over-the-loop-variable-considered-harmful.aspx\"相对=nofollow>链接埃里克利珀的博客提供了这是怎么回事更深入的(和技术上准确)的描述。

Adam's link to Eric Lippert's blog provides a more in-depth (and technically accurate) description of what's going on.

这篇关于如何在C#中绑定的lambda到一个foreach枚举?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆