Подтвердить что ты не робот

Когда использовать LINQ.ToList() или .ToArray()

После запуска этого кода:

var input = new List<T>( ... );
var result = input.Select( t => new U(t) );

U first1 = null;
foreach ( U u1 in result )
    if ( first1 == null )
        first1 = u1;

U first2 = null;
foreach ( U u2 in result )
    if ( first2 == null )
        first2 = u2;

Затем 'first1 == first2' оценивает значение false, даже если оба U завершают тот же T. Я еще не тестировал его, но я думаю, что можно сделать оценку true, связав .ToList() или. ToArray() на вызов Select().

В реальном коде, который намного сложнее, чем эта простая иллюстрация, следует использовать хорошее правило для принятия решения о добавлении .ToList() или .ToArray(). Мои первоначальные мысли - это любое ссылочное выражение, которое может повторяться более одного раза или, чтобы быть более безопасным, если потенциальные итерации не являются очевидными, любое ссылочное выражение, результат которого никогда не изменится.

4b9b3361

Ответ 1

К сожалению, я не думаю, что здесь существует хорошее "жесткое и быстрое" правило. Это зависит от того, как вы ожидаете, что результаты будут использованы, и что делает сам запрос.

Мои первоначальные мысли - это любое выражение, которое может повторяться более одного раза или, чтобы быть более безопасным, если потенциальные итерации не очевидны, любое выражение, результат которого никогда не изменится.

В общем случае, если вы собираетесь использовать результат запроса более одного раза, всегда рекомендуется хранить его через ToList() или ToArray(). Это особенно верно, если вы являетесь запросом LINQ, является "дорогим", поскольку он предотвращает запуск более дорогостоящей операции более одного раза.

Как правило, если вы только собираетесь перечислять результаты, я оставил бы его как IEnumerable<T>. Если вы планируете сохранять результаты или использовать результаты более одного раза, то их сохранение в коллекции может быть полезным.

Другим местом для просмотра является возвращение результатов в открытый API. Хотя часто бывает полезно возвращать IEnumerable<T>, в зависимости от ожидаемого варианта использования, вы можете рассмотреть возможность использования ToList(), чтобы предотвратить выполнение операции более одного раза.

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

Ответ 2

ToList вызывает конструктор List<T>(IEnumerable<T>) для создания List<T>, а ToArrary использует внутренний класс Buffer<T> для роста массива.

Если исходная коллекция (IEnumerable<T>) реализует интерфейс ICollection, эти два метода используют аналогичную логику кода для копирования данных.

ICollection.CopyTo(array, 0);  

В противном случае ToList будет динамически создавать List<T>. Пока ToArray копирует элемент один за другим в новый массив. Если массив заполнен, метод удваивает размер массива для хранения данных. Наконец, метод возвращает другой массив, основанный на размере исходных коллекций.