linq Last()如何工作?

时间:2010-05-20 10:14:28

标签: c# .net linq

我不明白当前可以为null,而last可以是一个对象,而最后一个是LINQ函数。我以为最后使用GetEnumerator并一直持续到current == null并返回该对象。但是你可以看到第一个GetEnumerator()。当前为null,最后以某种方式返回一个对象。

linq Last()如何工作?

var.GetEnumerator().Current
var.Last()

5 个答案:

答案 0 :(得分:18)

System.Core.dll上使用Reflector

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();
}

答案 1 :(得分:7)

Last()会调用GetEnumerator(),然后继续调用MoveNext() / Current,直到MoveNext()返回false,此时它会返回{{1}的最后一个值1}}检索。通常,Nullity不会用作序列中的终止符。

所以实现可能是这样的:

Current

(这可以通过public static T Last<T>(this IEnumerable<T> source) { if (source == null) { throw new ArgumentNullException("source"); } using (IEnumerator<T> iterator = source.GetEnumerator()) { if (!iterator.MoveNext()) { throw new InvalidOperationException("Empty sequence"); } T value = iterator.Current; while (iterator.MoveNext()) { value = iterator.Current; } return value; } } 循环实现,但上面更明确地显示了交互。这也忽略了直接访问最后一个元素的可能性。)

答案 2 :(得分:2)

在任何MoveNext()之前,枚举数的第一个值,就数组而言,是索引为-1的项目。
您必须执行一次MoveNext才能输入实际的集合 这样做是为了使枚举器的构造函数不起作用,并且这些构造是有效的:

while (enumerator.MoveNext()) {
      // Do Stuff
 }

if(enumerator.MoveNext()) {
      // Do Stuff
 } // This is identical to Linq's .Any(), essentially.

答案 3 :(得分:1)

请记住,调用GetEnumerator通常/每次都不会返回相同的Enumerator。此外,由于thing.GetEnumerator()会返回一个未初始化的新Enumerator(您尚未调用MoveNext()),thing.GetEnumerator().Current 将始终为null按照定义。

(我认为......)

答案 4 :(得分:1)

如果您在备注部分查看IEnumerator Interface,他们会说明以下内容:

  

最初,枚举器位于集合中的第一个元素之前。 在此位置,Current未定义。因此,在读取Current的值之前,必须调用MoveNext将枚举器前进到集合的第一个元素。

因此,您必须拨打MoveNext()一次才能获得第一项。否则你什么都不会。