c# - 流式运算符与延迟执行有何不同?

标签 c# linq

在 LINQ 中 Where 是一个流操作符。其中,OrderByDescending 是一个非流操作符。 AFAIK,流媒体运营商只收集下一个必要的项目。非流运算符(operator)一次评估整个数据流。

我看不到定义流媒体运营商的相关性。对我来说,延迟执行是多余的。以我编写自定义扩展并使用 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);
    }

无论哪种情况,Where 都需要计算每个元素以确定哪些元素满足条件。它产生的事实似乎只变得相关,因为运算符(operator)获得了延迟执行。

那么,流媒体运营商的重要性是什么?

最佳答案

有两个方面:速度和内存。

当您使用像 .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();

因为第一个示例在调用 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);

关于c# - 流式运算符与延迟执行有何不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10036033/

相关文章:

c# - Azure Kubernetes .NET Core 应用程序到 Azure SQL 数据库间歇性错误 258

c# - 反序列化不同类型的JSON数组

DataView 上的 LINQ

c# - Nlog:如何将嵌套诊断上下文值输出到日志文件?

c# - 用于 Linux 的 dotnet : Console Input Cursor Navigation

c# - 使用 LockBits 复制位图的矩形部分

c# - 在列表中添加对象的两个变量

c# - 将一个 IEnumerable<Type1> 的值添加到另一个 IEnumerable<Type2>

asp.net - Linq 查询无法转换为 SQL : how to optimize the code?

c# - 转换 lambda 表达式