LINQ Where是一个流媒体运营商.在哪里 - OrderByDescending非流媒体运营商.AFAIK,流媒体运营商只收集下一个必要的项目.非流式运算符一次评估整个数据流.
我没有看到定义流媒体运营商的相关性.对我来说,延期执行是多余的.以我编写自定义扩展并使用where运算符和orderby消耗它为例.
public static class ExtensionStuff
{
public static IEnumerable<int> Where(this IEnumerable<int> sequence, Func<int, bool> predicate)
{
foreach (int i in sequence)
{
if (predicate(i))
{
yield return i;
}
}
}
}
public static void Main()
{
TestLinq3();
}
private static void TestLinq3()
{
int[] items = { 1, 2, 3,4 };
var selected = items.Where(i => i < 3)
.OrderByDescending(i => i);
Write(selected);
}
private static void Write(IEnumerable<int> selected)
{
foreach(var i in selected)
Console.WriteLine(i);
}
Run Code Online (Sandbox Code Playgroud)
在任何一种情况下,都Where需要评估每个元素以确定哪些元素满足条件.它产量的事实似乎只是变得相关,因为运营商获得了延期执行.
那么,流媒体运营商的重要性是什么?
Str*_*ior 14
有两个方面:速度和记忆.
当您使用.Take()仅消耗原始结果集的一部分的方法时,速度方面变得更加明显.
// Consumes ten elements, yields 5 results.
Enumerable.Range(1, 1000000).Where(i => i % 2 == 0)
.Take(5)
.ToList();
// Consumes one million elements, yields 5 results.
Enumerable.Range(1, 1000000).Where(i => i % 2 == 0)
.OrderByDescending(i => i)
.Take(5)
.ToList();
Run Code Online (Sandbox Code Playgroud)
因为第一个示例在调用之前仅使用流式运算符,所以Take在Take停止计算之前,最终只会产生值1到10 .此外,一次只能将一个值加载到内存中,因此内存占用量非常小.
在第二个例子中,OrderByDescending不是流式传输,所以当Take取出第一个项目时,通过Where过滤器的整个结果必须放在内存中进行排序.这可能需要很长时间并产生大量内存.
即使您没有使用Take,内存问题也很重要.例如:
// Puts half a million elements in memory, sorts, then outputs them.
var numbers = Enumerable.Range(1, 1000000).Where(i => i % 2 == 0)
.OrderByDescending(i => i);
foreach(var number in numbers) Console.WriteLine(number);
// Puts one element in memory at a time.
var numbers = Enumerable.Range(1, 1000000).Where(i => i % 2 == 0);
foreach(var number in numbers) Console.WriteLine(number);
Run Code Online (Sandbox Code Playgroud)