C#LINQ相同数据的多重求值

问题描述 投票:0回答:2

给出一个拥有(并初始化一次)IEnumarable<T>的类:

public class MyClass
{
    public MyClass()
    {
        Values = Sequence(0, 10).Select(i => Convert(i));
    }

    public IEnumerable<string> Values { get; private set; }

    private static string Convert(int i)
    {
        string iStr = i.ToString();
        Console.WriteLine("Convert: " + iStr);
        return iStr;
    }

    private static IEnumerable<int> Sequence(int start, int end)
    {
        return Enumerable.Range(start, end - start + 1);
    }
}

为什么每次需要myClass.Values的评估值的用法都会重新评估它们?

例如:

static void Main(string[] args)
{
    MyClass myClass = new MyClass();

    foreach (var v in myClass.Values)
    {
        Console.WriteLine(v);
    }
    foreach (var v in myClass.Values)
    {
        Console.WriteLine("Value: " + v);
    }
}

这将打印20次“转换:”和“值:”。

[我知道将值另存为列表(例如,使用ToList())将解决此问题,但据我了解,一旦评估了值,便会从内存中使用值(就像我使用Lazy<T>然后Values.value),为什么情况不一样?

c# linq lazy-evaluation
2个回答
0
投票

这是IEnumerable<T>的正常行为。当在Select循环中调用每个项目时,实际上会为集合中的每个项目调用您的投影调用foreach(但显然您只调用了一次)。

因此,当您使用foreach循环进行循环时,IEnumerable对象将调用枚举器,并在集合中有可用项时获取下一项,类似于状态机。

[它跟踪在foreach循环中下一个项目被请求时正在枚举的当前项目,因此再次调用了Convert方法。


0
投票

[Materialize

© www.soinside.com 2019 - 2024. All rights reserved.