反转lambien函数的无数

时间:2011-09-16 14:21:08

标签: c# .net c#-4.0

我使用这个函数

创建了一个不可数的lambda函数
    static IEnumerable<Func<int>> MakeEnumerator(int[] values)
    {
        for (int a = 0; a < values.Length; a++)
        {
            yield return () => Values[a];
        }
    }

我无法使用LINQ将其反转或转换为数组,而不是所有值都成为最后一个函数。 示例代码(注意这只是演示了问题,它不是应用程序中的代码):

        int[] start = {1,2,3};

        IEnumerable<Func<int>> end = MakeEnumerator(start).Reverse<Func<int>>();

        foreach (Func<int> i in end)
        {
            Console.WriteLine(i());
        }

我认为问题出在MakeEnumerator函数中。我如何修改它以使其工作或者编写一个有效的替换反向函数。

2 个答案:

答案 0 :(得分:5)

问题是你正在捕获循环变量。你的所有代表都在捕获相同的变量,所以他们总会在你的用例中看到a的最新值......当你执行代理时它们将是values.Length + 1 。你可以简单地复制它:

for (int a = 0; a < values.Length; a++)
{
    int copy = a;
    yield return () => Values[copy];
}

或者(最好是IMO)使用foreach循环,当前需要相同的解决方法:

foreach (int value in values)
{
    int copy = value;
    yield return () => copy;
}

或者更好:

return values.Select(x => (Func<int>)(() => x));

或者:

Func<int, Func<int>> projection = x => () => x;
return values.Select(projection);

有关详细信息,请参阅Eric Lippert的博客文章"Closing over the loop variable considered harmful"。请注意,对于C#4.5,foreach的行为可能会发生变化。

答案 1 :(得分:2)

你所有的lambda表达式都是sharing the same a variable 由于您只是在循环结束后调用它们,因此a始终为3

你需要给每个人一个自己的变量:

for (int dontUse = 0; dontUse < values.Length; dontUse++)
{
    int a = dontUse;
    yield return () => Values[a];
}

在这段代码中,每个lambda表达式都有自己的a变量(因为它是在循环中的作用域),而这些单独的变量永远不会改变。