10

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

Nico
  • 12,493
  • 5
  • 42
  • 62
  • I think I may need to rephrase the question as it should be talking specifically about the ToList() function.. – Nico Jan 09 '14 at 06:29
  • I've updated my answer a little bit to make the point, because it's really important what you're calling `ToList()` on. – MarcinJuraszek Jan 09 '14 at 06:40

3 Answers3

15

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, not memcpy.

from Array.Copy Method (Array, Array, Int32)

MarcinJuraszek
  • 124,003
  • 15
  • 196
  • 263
  • 1
    +1 C/C++ function memmove, not memcpy. Array.Copy Method (Array, Array, Int32) – cat916 Jan 09 '14 at 06:36
  • I understand a block copy is going to be more efficient than enumeration, but isnt it still an O(n) operation? It definitely has to be for a collection of value types (e.g. `List().ToList()`), isnt it? Because each value has to be copied. But even for reference types, `memmove` has to be O(n) right? – nawfal Jun 16 '21 at 20:20
1

does the ToList() extension method (ICollection.CopyTo()) iterate through all objects of the Collection

It depends on how ICollection<T> is implemented in particular class.

For example, List<T> implementation just copies array (without iteration), because internally List<T> uses array as a storage. But nothing prevents you (or someone else) to write implementation, which will iterate though the source collection.

Where can I find the source for the extern void Copy() above

methods, marked by MethodImpl(MethodImplOptions.InternalCall), are implemented in unmanaged C++ code. I'm not sure, that there are any opened sources for them. But I suppose, that, ultimately, there's something like memcpy(...).

Dennis
  • 37,026
  • 10
  • 82
  • 150
-1

extern it means that function will be implemented in outside of C# code. It could be implemented in C/C++. More detail :

extern keyword

BenMorel
  • 34,448
  • 50
  • 182
  • 322
cat916
  • 1,363
  • 10
  • 18
  • 3
    I understand what the keyword `extern` means, what I am insterested in knowing is where can I locate the source file. I also cant seem to find which external code is being loaded from. – Nico Jan 09 '14 at 06:28
  • oh I see, let's this guy @Hans Passant . I don't know how to invite him to answer you :) – cat916 Jan 09 '14 at 06:31