Through the travels in StackOverflow there are many usages of the ToList()
extension method for an ICollection
(or classes that derive from ICollection<T>
).
I have pulled out the good ol' decompiler to have a look at how the ToList()
extension method is executed and does it enumerate the collection at anytime. Going through the source I came across:
[__DynamicallyInvokable]
public static List<TSource> ToList<TSource>(this IEnumerable<TSource> source)
{
if (source == null)
{
throw Error.ArgumentNull("source");
}
return new List<TSource>(source);
}
Now this is pretty straight forward, so the ToList()
extension method just creates a new List<T>
with the source object. Digging deeper into the List constructor shows this line.
ICollection<T> ts = collection as ICollection<T>;
//.. ommited code
ts.CopyTo(this._items, 0);
As you would, you would dig into the CopyTo
method. This is where I got stuck. After all the digging through method calls we get to the final extern
method call
[ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
[SecurityCritical]
internal static extern void Copy(Array sourceArray, int sourceIndex, Array destinationArray, int destinationIndex, int length, bool reliable);
My question is (although I cant seem to find it) does the ToList()
extension method (ICollection<T>.CopyTo()
) iterate through all objects of the Collection (Array) when executed?
Subquestion: Where can I find the source for the extern void Copy()
above?
Edit: I have edited the question directly as I realized after that I am trying to get a specification on an Interface and not implementation. Sorry
My question is (although I cant seem to find it) does the
ToList()
extension method(ICollection<T>.CopyTo())
iterate through all objects of the Collection (Array
) when executed?
No, it does not. It just copies the underlying array storage using Array.Copy
.
Update
Just to make sure my answer is interpreted correctly. ToList()
does not enumerate the source collection when it's being called directly on another List<T>
or T[]
array (or other collection which implements ICollection.CopyTo
without enumerator).
When you call ToList<>
e.g. on Enumerable.Range(0, 1000).ToList()
there will be an enumeration. Enumeration will be also performed when you use any LINQ method, e.g. myList.Select(x => x.PropertyName).ToList()
will cause enumeration.
End of update
void ICollection.CopyTo(Array array, int arrayIndex)
{
if (array != null && array.Rank != 1)
{
ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported);
}
try
{
Array.Copy(this._items, 0, array, arrayIndex, this._size);
}
catch (ArrayTypeMismatchException)
{
ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType);
}
}
which uses unmanaged c++ code to do that in efficient way:
This method is equivalent to the standard C/C++ function
memmove
, notmemcpy.