Say I have a simple array:
double[] myDoubleArray = new double[] { 0, 1, 2, 3, 4, 5 };
Is this as performant:
double last = myDoubleArray.Last();
as this?
double last = myDoubleArray[myDoubleArray.Length - 1];
Will Last() enumerate over the entire array even when it can make the above optimization?
If开发者_如何学Go I passed some other IEnumerable (say one that was yielded), Last() would have to enumerate the sequence. I prefer using Last(), because code looks cleaner, but I would not make a sacrifice if it enumerates the sequence.
No, it won't iterate all over elements. Here's the code of Enumerable.Last() from reflector. As you see, it makes such optimization
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();
}
No, Last
without a predicate optimizes for the IList<T>
case, including single-dimensional arrays.
With a predicate, it doesn't perform the optimization. In particular, it doesn't work backwards from the end (which could alter the results due to exceptions).
It's still going to be slightly faster to access the last element directly, but Last()
is more readable and will only be "constant time" different - it won't change an O(1) operation to O(N) in this case.
For more about Last
, see my Edulinq blog post about it.
Note that the optimization is not documented, so arguably you shouldn't rely on it. In practice, I can't imagine it changing to become O(N) :)
精彩评论