【问题标题】:Does List<T>.Last() enumerate the collection?List<T>.Last() 是否枚举集合?
【发布时间】:2012-06-21 16:56:25
【问题描述】:

考虑到List 的边界已知,.Last() 是否枚举集合?

我问这个是因为documentation 说它是由Enumerable 定义的(在这种情况下,它需要枚举集合)

如果它确实枚举了集合,那么我可以简单地按索引访问最后一个元素(正如我们知道List&lt;T&gt;.Count),但必须这样做似乎很愚蠢。 ...

【问题讨论】:

  • 如果你知道你有一个List&lt;T&gt;,那么只需快速访问最后一个元素,而不依赖Last() 中可能的未记录优化。 (碰巧Last()确实检查接收器是否实现IList&lt;T&gt;,并优化这种情况。)
  • @dlev 是的,正如我所提到的,我知道我可以做到这一点......我特别询问.Last的实施
  • 我很确定实现会检查 List&lt;T&gt; 并尽可能按索引访问最后一个元素。
  • 许多 LINQ 扩展检查索引类型作为优化。如果 Last() 也这样做,我不会感到惊讶。当然,这将是实现定义的,不应依赖。
  • 对,但我的意思是你不应该依赖行为,因为它没有被记录为这样(即使它确实 执行优化。)

标签: c# .net list collections linq-to-objects


【解决方案1】:

如果集合是IEnumerable&lt;T&gt; 而不是IList&lt;T&gt;,它会枚举集合(使用数组或列表时将使用索引)。

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&lt;T&gt;... 但您的第一行显示“是”;-)
  • @MatthewPK 它是“是的,如果它不是 IList&lt;T&gt;,它将迭代整个可枚举”有点令人困惑,但正确。
  • @TimSchmelter 然后我很困惑....List&lt;T&gt; 肯定实现了IList&lt;T&gt; 所以....我的标题不会是“否”吗?我知道这是语义......我只是想知道我是否遗漏了你的答案......
  • @TimSchmelter 你的回答完全被理解(并且会被接受)......我只是觉得措辞令人困惑:)
猜你喜欢
  • 2014-01-27
  • 1970-01-01
  • 2012-07-28
  • 1970-01-01
  • 2010-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-21
相关资源
最近更新 更多