流模式(延迟评估)与非流模式(急切评估)

在使用延迟执行的 LINQ 方法中,有些需要一次评估一个值。以下代码:

var lst = new List<int>() {3, 5, 1, 2};
var streamingQuery = lst.Select(x => {
    Console.WriteLine(x);
    return x;
});
foreach (var i in streamingQuery) {
    Console.WriteLine($"foreach iteration value: {i}");
}

将输出:

3
foreach 迭代值:3
5
foreach 迭代值:5
1
foreach 迭代值:1
2
foreach 迭代值:2

因为传递给 Select 的函数是在 foreach 的每次迭代中计算的。这称为流模式惰性评估

其他 LINQ 方法 - 排序和分组运算符 - 需要评估所有值,然后才能返回任何值:

var nonStreamingQuery = lst.OrderBy(x => {
    Console.WriteLine(x);
    return x;
});
foreach (var i in nonStreamingQuery) {
    Console.WriteLine($"foreach iteration value: {i}");
}

将输出:

3
5
1
2
foreach 迭代值:1
foreach 迭代值:2
foreach 迭代值:3
foreach 迭代值:5

在这种情况下,因为必须以递增的顺序为 foreach 生成值,所以必须首先评估所有元素,以便确定哪个是最小的,哪个是下一个最小的,依此类推。这称为非流模式急切评估

可以在 MSDN - C#VB.NET 中找到特定 LINQ 方法是使用流式还是非流式模式。