2010-01-21 1 views
7

OOC: Из любопытстваOOC: В чем разница между ToList() и литьем в List <T> в .NET?

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

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

2 - Отсутствуют локальные «названные» переменные, объявленные в теле функции.

я придумал ниже решения (BTW: это может быть улучшено в любом случае?)

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

Спасибо!

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

EDIT: ошибка во время выполнения является 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(); 
} 

ответ

12

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, а не список. Помните, что он должен поддерживать генераторы (которые ленивы оцениваются), поэтому для него не имеет смысла быть чем-то похожим на список внизу.

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

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

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

Enumerable.Range(min, length); 

или

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

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

+0

Спасибо, я только что проверил это; поэтому кажется, что мы не получаем «Enumerable.Range (min, max, step)» или «Enumerable.Range (min, max, x => x * x)», правильно? –

+0

Не прямо, но вы можете сделать что-то вроде 'Enumerable.Range (min, length) .Where (x => (x-min)% step == 0)' и 'Enumerable.Range (min, length). Выберите (x => x * x); 'получить эквивалент этих –

+0

Также обратите внимание, что второй параметр в Enumerable.Range равен LENGTH, а не MAX –

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