OOC: из любопытства
Так, так же мало осуществления и ради изучения, я решил проверить, смог ли я реализовать очень простую рекурсивную функцию, которая возвратила бы a List<int>
, но со следующими ограничениями:
1-результат должен быть возвращен самой функцией (в противоположность переданному как аргумент a void
функция).
2 - Никакие локальные "именованные" переменные не объявляются в теле функции.
Я предложил решение ниже (BTW: это может быть улучшено всегда?)
При выполнении этого я изучил это 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();
}
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. Помните, что он должен поддерживать генераторы (которые лениво оцениваются), так что не имеет смысла быть чем-то вроде списка внизу.
Btw, вы рассмотрели встроенную функцию Enumerable.Range
?
, что-то получено из списка
или что-то с допустимым преобразованием в >
, в противном случае он не удается с помощью InvalidCastexception
. Tolist ()
работает на любом IENumerable. Tolist ()
всегда создает новую копию списка, даже если у вас уже есть список. Лить что-то в списке
, как правило, не производит копию списка - она просто дает вам новый тип компиляции для того же объекта. Кажется трудным способом оптимизации, почему бы не запустить APC? вы получите аналогичные преимущества производительности.
-121--4067306-ToList отличается от (casting) в List.
ToList принимает любой IEnumerable (списки, массивы, словари, наборы и т.д.) и превращает его в список.
Casting to List принимает объект, который уже является списком некоторого рода, и помечает его как список. Пример:
// 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. Помните, что он должен поддерживать генераторы (которые оцениваются лениво), поэтому не имеет смысла, чтобы это было что-то вроде списка ниже.
Btw, вы просмотрели встроенную функцию Enumerable.Range
?
Кстати, лучший способ создать список целых чисел:
Enumerable.Range(min, length);
или
Enumerable.Range(min, max-min+1);
Но это не помогает вам учиться, поэтому кудо вам!:)