gpt4 book ai didi

c# - 枚举 lambdas 没有正确绑定(bind)作用域?

转载 作者:可可西里 更新时间:2023-11-01 08:29:33 25 4
gpt4 key购买 nike

考虑以下 C# 程序:

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

public class Test
{
static IEnumerable<Action> Get()
{
for (int i = 0; i < 2; i++)
{
int capture = i;
yield return () => Console.WriteLine(capture.ToString());
}
}

public static void Main(string[] args)
{
foreach (var a in Get()) a();
foreach (var a in Get().ToList()) a();
}
}

在 Mono 编译器下执行时(例如 Mono 2.10.2.0 - 粘贴到 here ),它会写入以下输出:

0
1
1
1

这对我来说似乎完全不合逻辑。当直接迭代 yield 函数时,for 循环的范围被“正确”(据我所知)使用。但是当我先将结果存储在列表中时,作用域总是最后一个 Action ?!

我可以假设这是 Mono 编译器中的错误,还是我遇到了 C# 的 lambda 和 yield-stuff 的神秘极端情况?

顺便说一句:当使用 Visual Studio 编译器(以及要执行的 MS.NET 或单声道)时,结果是预期的 0 1 0 1

最佳答案

我会告诉你它是 0 1 1 1 的原因:

foreach (var a in Get()) a();

在这里您进入 Get 并开始迭代:

i = 0 => return Console.WriteLine(i);

yield 返回函数并执行函数,将 0 打印到屏幕,然后返回到 Get() 方法并继续。

i = 1 => return Console.WriteLine(i);

yield随函数返回并执行函数,打印1到屏幕,然后返回到Get()方法继续(才发现它必须停止)。

但是现在,您不是在每个项目发生时对其进行迭代,而是构建一个列表,然后对该列表进行迭代。

foreach (var a in Get().ToList()) a();

您所做的与上面不同,Get().ToList() 返回一个列表或数组(不确定是哪个)。所以现在发生了这种情况:

i = 0 => return Console.WriteLine(i);

在你的 Main() 函数中,你会在内存中得到以下内容:

var i = 0;
var list = new List
{
Console.WriteLine(i)
}

你回到 Get() 函数:

i = 1 => return Console.WriteLine(i);

返回到您的 Main()

var i = 1;
var list = new List
{
Console.WriteLine(i),
Console.WriteLine(i)
}

然后做

foreach (var a in list) a();

这将打印出 1 1

它似乎忽略了您确保在返回函数之前封装了值。

关于c# - 枚举 lambdas 没有正确绑定(bind)作用域?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22200248/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com