OOC: В чем разница между ToList () и приведением к списку <T>в .NET? - PullRequest
8 голосов
/ 21 января 2010

ООК: из любопытства

Итак, в качестве небольшого упражнения и ради обучения я решил проверить, могу ли я реализовать очень простую рекурсивную функцию, которая будет возвращать List<int>, но со следующими ограничениями:

1- Результат должен быть возвращен самой функцией (в отличие от передачи в качестве аргумента функции void).

2 - В теле функции не объявлено локальных «именованных» переменных.

Я придумал решение ниже (кстати: можно ли это как-нибудь улучшить?)

При этом я узнал, что ToList() - это не то же самое, что приведение к List<T> (см. Пример ниже). Кто-нибудь может объяснить, что происходит под капотом и в чем разница между ними?

Спасибо!

PS - я использую версию 4.0 (на случай, если это имеет значение).

РЕДАКТИРОВАТЬ: ошибка времени выполнения Unable to cast object of type '<ConcatIterator>d__71'1[System.Int32]' to type 'System.Collections.Generic.List'1[System.Int32]'

public static List<int> SomeIntegers(int min, int max)
{
    //assume max >= min for simplicity  
    if (min == max)
        return new List<int>() { min };

    // runtime error 
    //return (List<int>)(SomeIntegers(min, max - 1).Concat(new List<int>() { max }));   

    //works
    return (SomeIntegers(min, max - 1).Concat(new List<int>() { max })).ToList(); 
}

Ответы [ 3 ]

12 голосов
/ 21 января 2010

ToList - это не то же самое, что (приведение) к списку.

ToList берет любой IEnumerable (списки, массивы, словари, наборы и т. Д.) И превращает его в список.

Приведение к списку берет объект, который уже является каким-то списком, и помечает его как список. Пример:

// fail -- arrays are not lists
var not_a_list = (List<int>)int[];
// success: arrays *are* IEnumerable, so you can convert them to a list.
var list_from_array = new [] { 1,2,3,4,5 }.ToList();
// success: WorkflowRoleCollection derives from List<WorkflowRole>
var derived_from_list = (List<WorkflowRole>) new WorkflowRoleCollection();

В вашем случае Concat возвращает IEnumerable, а не List. Помните, что он должен поддерживать генераторы (которые лениво оцениваются), поэтому не имеет смысла для него быть чем-то вроде списка внизу.

Кстати, вы уже взглянули на встроенную функцию Enumerable.Range?

3 голосов
/ 21 января 2010
  • Приведение работает только в том случае, если у вас действительно есть List<T>, что-то, полученное из List<T>, или что-то с допустимым преобразованием типа в List<T>, в противном случае оно завершается с InvalidCastException. ToList() работает на любом IEnumerable.
  • ToList() всегда создает новую копию списка, даже если у вас уже есть список. Приведение чего-либо к List<T> обычно не создает копию списка - он просто дает вам новый тип времени компиляции для того же объекта.
2 голосов
/ 21 января 2010

Кстати, лучший способ создать список целых чисел:

Enumerable.Range(min, length);

или

Enumerable.Range(min, max-min+1);

Но это не поможет тебе учиться, так что слава тебе! :)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...