linq Last()如何工作?
我不明白当前可以为null,最后一个可以是一个对象,而最后一个是LINQ函数。 我以为最后使用GetEnumerator并一直持续到current == null并返回该对象。 但是你可以看到第一个GetEnumerator()。当前为null,最后以某种方式返回一个对象。
linq Last()如何工作?
var.GetEnumerator().Current var.Last()
从在System.Core.dll
上使用Reflector :
public static TSource Last(this IEnumerable source) { if (source == null) { throw Error.ArgumentNull("source"); } IList list = source as IList ; if (list != null) { int count = list.Count; if (count > 0) { return list[count - 1]; } } else { using (IEnumerator enumerator = source.GetEnumerator()) { if (enumerator.MoveNext()) { TSource current; do { current = enumerator.Current; } while (enumerator.MoveNext()); return current; } } } throw Error.NoElements(); }
Last()
将调用GetEnumerator()
,然后继续调用MoveNext()
/ Current
直到MoveNext()
返回false,此时它返回Current
的最后一个值。 通常,Nullity不用作序列中的终止符。
所以实现可能是这样的:
public static T Last(this IEnumerable source) { if (source == null) { throw new ArgumentNullException("source"); } using (IEnumerator iterator = source.GetEnumerator()) { if (!iterator.MoveNext()) { throw new InvalidOperationException("Empty sequence"); } T value = iterator.Current; while (iterator.MoveNext()) { value = iterator.Current; } return value; } }
(这可以用foreach
循环实现,但是上面更明确地显示了交互。这也忽略了直接访问最后一个元素的可能性。)
在任何MoveNext()之前,枚举数的第一个值在数组的情况下是索引-1处的项。
您必须执行一次MoveNext才能输入实际的集合。
这样做是为了使枚举器的构造函数不起作用,并且这些构造是有效的:
while (enumerator.MoveNext()) { // Do Stuff } if(enumerator.MoveNext()) { // Do Stuff } // This is identical to Linq's .Any(), essentially.
请记住,每次调用GetEnumerator
通常/必然不会返回相同的Enumerator
。 此外,因为thing.GetEnumerator()
返回一个新的Enumerator
,它将启动未初始化(你还没有调用MoveNext()
), thing.GetEnumerator().Current
根据定义, thing.GetEnumerator().Current
将始终为null。
(我认为…)
如果你看一下IEnumerator Interface到Remarks部分,他们会说出以下内容:
最初 ,枚举数位于集合中的第一个元素之前 。 在这个位置,Current是未定义的。 因此,在读取Current的值之前,必须调用MoveNext将枚举器前进到集合的第一个元素。
因此,您必须调用MoveNext()
一次才能获得第一个项目。 否则你什么也得不到。