Возвращает ли LINQ Enumerable запрос копию или ссылку? - PullRequest
2 голосов
/ 19 апреля 2020

Я хочу скопировать Skip и Take из C# в C ++ для создания фрагментов. Примерно так:

std::vector<int> numbers = { 59, 82, 70, 56, 92, 98, 85 };

auto slice = grades.skip(3).take(2); // {56, 92}

После проверки работы срезов в JS и Golang я в основном понимаю, что они предпочитают теневое копирование, а не глубокое. Я понимаю компромисс между выделением новой памяти, но наличием независимых данных и связанными данными путем копирования только ссылки.

Теперь я также проверил Пропустить и Взять , но Я не могу найти, какой из них они используют.

Короче говоря, они возвращают какой-то Enumerator в начале и в конце? Или они создают совершенно новый IEnumerable?

Edit

Итак, я не знал, что мы можем получить доступ к исходному коду (упоминается в комментариях). И, видимо, возвращает итератор:

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

Ответы [ 2 ]

3 голосов
/ 19 апреля 2020

Skip, Take и другой метод LINQ не возвращает ни одной коллекции. Они возвращают IEnumerable интерфейс, который позволяет получить следующий элемент из базового источника. Это концепция ленивой загрузки. Skip и Take фактически не фильтруют вашу коллекцию, пока вам не понадобится результат.

Вы можете скопировать все элементы из IEnumerable в некоторую коллекцию с помощью метода ToArray или ToList.

Артикул для справки: https://odetocode.com/blogs/scott/archive/2008/10/01/lazy-linq-and-enumerable-objects.aspx

2 голосов
/ 19 апреля 2020

Linq возвращает новые ссылки только для базовых типов (int, string, double e cc ..). IEnumerable будет таким же экземпляром исходного списка, вы должны вызвать ToList или ToArray, чтобы создать новую коллекцию.

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