代码之家  ›  专栏  ›  技术社区  ›  Lambda Fairy

为什么“.Select(…).Last()”是优化的,而“.Select(…).Last(…)”不是优化的?

  •  15
  • Lambda Fairy  · 技术社区  · 6 年前

    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
    

    但当我回电给 最后 ,它从一开始就遍历整个列表:

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

    另一方面:

    怎样 回调大小写未优化。但这并不能解释

    实现起来似乎也不难:据我所见,所需要的只是一个额外的方法 i参与<T>

    缺乏优化也可能令人惊讶。由于这些重载具有相同的名称,因此可以假设它们也以类似的方式进行了优化。(至少我是这么想的。)

    1 回复  |  直到 6 年前
        1
  •  1
  •   Monticola Explorator    6 年前

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

    练习),然后向后迭代可以允许提前退出循环。

    对于一个通用的实现来说,这个假设太牵强了 Last(Func<T,bool>) . 一般来说,不能假设满足谓词的最后一个元素更接近集合的末尾。那个 优化 很适合你的例子( Last(x=>true) 优化 表现更差( Last(x=>false) ).