List<T>.Last()方法会枚举集合吗?

10
考虑到已知 List 的边界,.Last() 是否会枚举该集合?
我问这个问题是因为文档说它由Enumerable定义(在这种情况下需要枚举集合)。
如果它确实枚举集合,那么我可以通过索引简单地访问最后一个元素(因为我们知道List<T>.Count),但这似乎很傻。

如果你知道自己有一个 List<T>,那么不要依赖于可能未经记录的优化程序,在快速方式下访问最后一个元素。(恰好 Last() 会检查接收器是否实现了 IList<T> 并对这种情况进行了优化。) - dlev
@dlev 是的,正如我所提到的,我知道我可以这样做...我特别询问关于.Last实现的问题 - Matthew
我非常确定该实现会检查 List<T> 并尽可能通过索引访问最后一个元素。 - Lee
很多LINQ扩展都会检查索引类型以进行优化。如果Last()也这样做,我不会感到惊讶。当然,这将是实现定义的,不应依赖于它。 - itsme86
没错,但我的意思是你不应该依赖这种行为,因为它并没有被记录下来(尽管它确实执行了优化)。 - dlev
1个回答

11

如果集合是 IEnumerable<T> 而不是 IList<T>(使用 Array 或 List 会使用索引),则它将枚举集合。

Enumerable.Last 的实现方式如下(使用ILSpy):

public static TSource Last<TSource>(this IEnumerable<TSource> source)
{
    if (source == null)
    {
        throw Error.ArgumentNull("source");
    }
    IList<TSource> list = source as IList<TSource>;
    if (list != null)
    {
        int count = list.Count;
        if (count > 0)
        {
            return list[count - 1];
        }
    }
    else
    {
        using (IEnumerator<TSource> enumerator = source.GetEnumerator())
        {
            if (enumerator.MoveNext())
            {
                TSource current;
                do
                {
                    current = enumerator.Current;
                }
                while (enumerator.MoveNext());
                return current;
            }
        }
    }
    throw Error.NoElements();
}

你提供的代码证明了它不会导致List<T>的枚举...但是你的第一行说“是”;-) - Matthew
2
@MatthewPK 这句话的意思是:“如果枚举不是 IList<T>,那么它将遍历整个枚举。”虽然有点令人困惑,但是是正确的。 - dlev
1
@TimSchmelter 那我有点困惑了... List<T> 明显实现了 IList<T>,所以... 我的标题不应该是“否”吗?我知道这只是纯粹的语义问题... 只是想知道你的回答中是否有什么我没注意到的东西... - Matthew
1
@TimSchmelter,我完全理解您的答案(并将接受它)...只是我认为措辞有点令人困惑 :) - Matthew

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接