2014-01-09 2 views
7

Через путешествие в StackOverflow есть много обыкновений методы ToList() расширения за ICollection (или классов, которые являются производными от ICollection<T>).ли Список <T> .ToList() перечислить коллекцию

Я вытащил декомпилятор хорошего ol ', чтобы посмотреть, как выполняется метод расширения ToList(), и он перечисляет коллекцию в любое время. Проходя через источник, я наткнулся на:

[__DynamicallyInvokable] 
public static List<TSource> ToList<TSource>(this IEnumerable<TSource> source) 
{ 
    if (source == null) 
    { 
     throw Error.ArgumentNull("source"); 
    } 
    return new List<TSource>(source); 
} 

Теперь это довольно прямо вперед, поэтому метод ToList() расширения просто создает новый List<T> с исходным объектом. Копая глубже в конструктор списка, показывает эту строку.

ICollection<T> ts = collection as ICollection<T>; 
//.. ommited code 
ts.CopyTo(this._items, 0); 

Как бы вы, вы бы вырыть в метод CopyTo. Здесь я застрял. Ведь копаться вызовов метода мы получаем до конечного вызова extern метода

[ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] 
[SecurityCritical] 
internal static extern void Copy(Array sourceArray, int sourceIndex, Array destinationArray, int destinationIndex, int length, bool reliable); 

Мой вопрос (хотя я не могу показаться, чтобы найти его) делает метод ToList() расширения (ICollection<T>.CopyTo()) перебрать все объекты Collection (Массив) при исполнении?

Подтверждение: Где я могу найти источник для extern void Copy() выше?

Редактировать: Я отредактировал этот вопрос непосредственно, как я понял после этого, я пытаюсь получить спецификацию интерфейса, а не реализацию. К сожалению

+0

Я думаю, что, возможно, придется перефразировать вопрос, как следует говорить конкретно о функции ToList() .. – Nico

+0

Я обновил мой ответ немного, чтобы сделать точку, потому что это на самом деле важно, что вы вызываете 'ToList()' on. – MarcinJuraszek

ответ

11

Мой вопрос (хотя я не могу показаться, чтобы найти его) делает ToList() метод расширения (ICollection<T>.CopyTo()) перебора всех объектов коллекции (Array) при выполнении ?

Нет, это не так. Он просто копирует хранилище базового массива, используя Array.Copy.


Update

Просто, чтобы убедиться, что мой ответ правильно интерпретированы. ToList() не перечисляет исходную коллекцию, когда она вызывается непосредственно на другом List<T> или T[] массив (или другая коллекция, которая реализует ICollection.CopyTo без перечислителя).

Когда вы звоните ToList<>, например. на Enumerable.Range(0, 1000).ToList() будет перечисление. Перечисление также будет выполняться при использовании любого метода LINQ, например. myList.Select(x => x.PropertyName).ToList() приведет к перечислению.

Конец обновления


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

который использует неуправляемый C++ код, чтобы сделать это эффективно:

Этот метод эквивалентен функции стандартной C/C++ memmove, а не memcpy.

из Array.Copy Method (Array, Array, Int32)

+1

+1 Функция C/C++ memmove, а не memcpy. Метод Array.Copy (массив, массив, Int32) –

1

делает метод расширения ToList() (ICollection.CopyTo()) перебрать все объекты коллекции

Это зависит от того, как ICollection<T> осуществляется в конкретном классе.

Например, List<T> реализация просто копирует массив (без итерации), потому что внутри List<T> использует массив в качестве хранилища. Но ничто не мешает вам (или кому-то еще) писать реализацию, которая будет итерировать, хотя исходная коллекция.

Где я могу найти источник для экстерном ничтожной Copy() выше

методов, отмеченное MethodImpl(MethodImplOptions.InternalCall), реализованы в неуправляемом коде C++. Я не уверен, что для них есть открытые источники. Но я полагаю, что, в конечном счете, есть что-то вроде memcpy(...).

0

extern Это означает, что функция будет реализована вне кода C#. Он может быть реализован на C/C++.Подробнее:

extern keyword

+2

Я понимаю, что означает ключевое слово 'extern', то, чему я не доверяю, - это где я могу найти исходный файл. Я также не могу найти, с какого внешнего кода загружается. – Nico

+0

О, я вижу, давайте этот парень @ Хасс Пассант. Я не знаю, как пригласить его ответить вам :) –

Смежные вопросы