Как стать автором
Обновить

Комментарии 19

А эта фича связана только с числовыми индеками массивов, или она более общая, типа обобщения двух итераторов в произвольной коллекции, как это попытались сделать в С++?

А ведь можно двигаться еще дальше и получить "генераторы списков"...

В шарпе не итераторы а энумераторы, они похожи но семантически разные. Энумераторы не представляют собой позицию в контейнере, они могут только выдавать текущий элемент и смещаться на следующий.
По контракту энумератор не должен уметь сравнивать себя с другим энумератором той же коллекции, так что фича про числовые индексы, большего и не надо.


А генераторы списков в шарпе с самого начала есть, даже yield return для их удобного написания завезли.

НЛО прилетело и опубликовало эту надпись здесь

Да. Конечно. Поправил. Спасибо за обратную связь

Очень похоже на срезы в питоне, только нет возможности указания шага

Да. Именно так. Пока не подвезли. Думаю скоро добавят

Меньше нагрузка на память.

Почитал документацию - range на массивы создаёт копию массива в нужном срезе, т.е. я не понял, почему нагрузка на память меньше. Тут ведь всё ещё хуже - новый синтаксис скрывает аллокации потенциально больших данных. Согласно той же документации, копирования нет только на Span и Memory. Т.е. нужно обращать внимание на тип коллекции, чтобы понять, будет выделение памяти или нет. И со Span'ом тоже спорный вопрос. Допустим, у меня есть массив в мегабайт, далее я создал range на 3 элемента и собираюсь пользоваться только им - не получится ли так, что в памяти будет болтаться 1 мегабайт бесхозной памяти, потому что Span удерживает ссылку на массив в целом?

Да, нагрузка на память в Решении 5 ровно такая же, как в Решении 1. Под капотом вызывается RuntimeHelpers.GetSubArray, который создаёт новый массив.

есть массив в мегабайт, далее я создал range на 3 элемента и собираюсь пользоваться только им - не получится ли так, что в памяти будет болтаться 1 мегабайт бесхозной памяти, потому что Span удерживает ссылку на массив в целом

Так и получится. Чудес нет - либо выделяем новый массив из 3 элементов, и старый будет удалён сборщиком мусора, либо делаем AsMemory / AsSpan- очень быстро и не выделяет память, но удерживает большой массив.

Вообще в подобной статье было бы здорово упомянуть AsMemory & AsSpan, они тоже работают с Range:

var numbers = new int[] { 5, 1, 4, 2, 3, 7 };
Memory<int> result = numbers.AsMemory()[2..5];

Так и получится. Чудес нет

Согласен. Но в данной статье (и других похожих) делается вывод, что ranges являются (помимо прочего) решением проблем с памятью. Хотя по факту это просто синтаксический сахар, и ситуация мало поменялась, только добавилось новых подводных камней :) Я на это хотел обратить внимание.

"Вызовы ToListToArray проходятся по коллекции и выделяют новую память.  "

Уже нет , мы это оптимизировали , теперь мы работает с абстракциями объектов в памяти , тут выделяется память только на алокацию типа (копейка), а потом мы присваеваем ссылку на объект.

(понятное дело эта оптимизация работает до первого изменения)

не там смотрите , CLR

Можно ошибиться при передаче параметров в методы Skip и  Take (относится к начинающим программистам). 

Где тут можно ошибиться когда методы так и называются "пропустить" и "взять", и передать только целоцисленное значение

https://referencesource.microsoft.com/#system.core/system/linq/Enumerable.cs,591

public static IEnumerable<TSource> Take<TSource>(this IEnumerable<TSource> source, int count) {
    if (source == null) throw Error.ArgumentNull("source");
    return TakeIterator<TSource>(source, count);
}

Имхо половина аргументов в статье высосона из пальца

Вы не работали с начинающими программистами

Круто. До 9 версии тоже дойдем

Skip() Take() гораздо лучше читаются, чем эти браинфаки

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории