Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 流式处理操作符与延迟执行有何不同?_C#_Linq - Fatal编程技术网

C# 流式处理操作符与延迟执行有何不同?

C# 流式处理操作符与延迟执行有何不同?,c#,linq,C#,Linq,在LINQ中,其中是流式操作符。其中asOrderByDescending是非流式操作符。好吧,流媒体运营商只收集下一个需要的项目。非流式操作符一次评估整个数据流 我看不出定义流媒体运营商的相关性。对我来说,延迟执行是多余的。例如,我编写了一个自定义扩展,并使用where操作符和orderby使用它 public static class ExtensionStuff { public static IEnumerable<int> Where(this IEnumerabl

在LINQ
中,其中
是流式操作符。其中as
OrderByDescending
是非流式操作符。好吧,流媒体运营商只收集下一个需要的项目。非流式操作符一次评估整个数据流

我看不出定义流媒体运营商的相关性。对我来说,延迟执行是多余的。例如,我编写了一个自定义扩展,并使用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);
    }
公共静态类扩展插件
{
公共静态IEnumerable,其中(此IEnumerable序列,Func谓词)
{
foreach(按顺序输入i)
{
if(谓语(i))
{
收益率i;
}
}
}
}
公共静态void Main()
{
TestLinq3();
}
私有静态void TestLinq3()
{
int[]项={1,2,3,4};
所选变量=项目。其中(i=>i<3)
.OrderByDescending(i=>i);
写入(选定);
}
私有静态无效写入(已选择IEnumerable)
{
foreach(所选中的var i)
控制台写入线(i);
}
在这两种情况下,
其中
需要评估每个元素,以确定哪些元素符合条件。它产生的事实似乎只有在操作员获得延迟执行的情况下才有意义


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

有两个方面:速度和内存

当您使用像
.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
,内存问题也可能很重要。例如:

// 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);
它的收益率似乎只是因为 运算符获得延迟执行

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

也就是说,您不能使用缓冲/非流扩展方法处理无限序列-而您可以仅使用流扩展方法“运行”这样的序列(直到您中止为止)

以这种方法为例:

public IEnumerable<int> GetNumbers(int start)
{
    int num = start;

    while(true)
    {
        yield return num;
        num++;
    }
}

OrderBy()
在这种情况下不起作用,因为它必须在发出单个数字之前穷尽地枚举结果。

只是为了明确;在您提到的例子中,where-streams并没有什么好处,因为orderby无论如何都会把整个东西都吸进去。然而,有时使用流媒体的优势(其他答案/评论给出了示例),因此所有LINQ运营商都尽其所能流媒体。Orderby streams尽可能多地,而这恰好不是很多。其中流非常有效。

项中使用大约20亿整数重试。
@cHao或无限序列,或从开放网络流派生的序列。在某些情况下,Linq不能延迟执行。有些操作需要对IEnumerable进行slurping。不是Where(),而是一次一个。但是OrderBy是绝对的,除非您知道所有的集合项,否则无法对集合进行排序。我最喜欢的是Enumerable.Reverse(),它打破了IEnumerable规则。在IList上进行O(n)存储和O(n)执行时,没有得到令人震惊的优化。草率。挑剔,但它是无限的,只是每个结果都不是唯一的。它最终会溢出,但它会进行包装,因此它可以溢出无限次。(只要您不在选中的块中。)您可以只拥有
while(true)yield return 4如果你愿意。是否有LINQ操作符的流位于
Where
OrderBy
之间?@ZevSpitz我想这取决于你如何定义你的术语
SkipWhile
可能符合条件,具体取决于您如何定义“流”的数量。将流式处理定义为能够一次解析一个结果(例如,
Select
),而非流式处理需要所有值才能计算第一个值(例如,
OrderBy
)。根据这个定义,为什么
边跳
选择
的流量要少呢?第一次迭代不需要所有的值。@ZevSpitz您使用的是严格的二进制定义,其中有些东西流或不流,而不是模拟定义,其中有些东西可以流到给定的程度
SkipWhile
不需要使用所有输入序列来返回第一个项目,但它需要使用任意百分比的输入序列,在这一点上,它会切换到使用输入序列中的一个项目来返回每个结果。所以,这也是为什么我说这取决于你如何定义你的术语;在此上下文中没有一个定义明确的定义。根据您的逻辑,
其中
应被视为间歇流式传输和非流式传输。但是确定是否将值传递给下一个操作符/
foreach
的某些条件并不会从根本上改变查询的行为;当需要传递给其他运算符时,可以精确计算每个值
OrderBy
是非常不同的——第一个结果需要对所有结果进行评估。
foreach (var num in GetNumbers(0).Where(x => x % 2 == 0))
{
    Console.WriteLine(num);
}