gpt4 book ai didi

c# - 为什么 `.Select(...).Last()` 被优化,而 `.Select(...).Last(...)` 没有被优化?

转载 作者:可可西里 更新时间:2023-11-01 07:48:13 26 4
gpt4 key购买 nike

考虑以下枚举器:

var items = (new int[] { 1, 2, 3, 4, 5 }).Select(x =>
{
Console.WriteLine($"inspect {x}");
return x;
});

这会产生元素 [1, 2, 3, 4, 5] ,在它们被消耗时打印出来。

当我调用 Last此枚举器上的方法,它会触发仅访问单个元素的快速路径:

items.Last();
inspect 5

但是当我将回调传递给 Last 时, 它从头开始遍历整个列表:

items.Last(x => true);
inspect 1
inspect 2
inspect 3
inspect 4
inspect 5

查看 .NET Core 源代码,我发现:

另一方面:

这解释了如何未优化回调案例。但它没有解释原因

从概念上讲,如果至少有一个元素满足谓词(这在实践中很可能发生),则向后迭代可能允许提前退出循环。

实现起来似乎也不难:据我所见,只需要在 IPartition<T> 上添加一个方法即可.

缺乏优化也可能令人惊讶。由于这些重载共享相同的名称,人们可能会认为它们也以类似的方式进行了优化。 (至少我是这么想的。)

鉴于优化此案例的这些原因,为什么 LINQ 的作者选择不这样做?

最佳答案

Last()可以始终针对允许在恒定时间内访问集合的最后一个元素的集合进行优化 ( O(1) )。对于这些集合,您可以直接访问最后一个元素,而不是迭代所有集合并返回最后一个元素。

Conceptually, if at least one element satisfies the predicate (which is likely in practice), then iterating backward may allow for exiting the loop early.

这个假设对于 Last(Func<T,bool>) 的通用实现来说太牵强了。 .一般来说,您不能假设满足谓词的最后一个元素更接近集合的末尾。 优化 对您的示例(Last(x=>true))很有效,但对于每个这样的示例,都可能有一个相反的示例,其中优化 表现更差(Last(x=>false))。

关于c# - 为什么 `.Select(...).Last()` 被优化,而 `.Select(...).Last(...)` 没有被优化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54035356/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com