Работу методов LINQ можно разделить на три этапа: 1. получение источника данных, 2. создание запроса, 3. выполнение запроса. В зависимости от того, какой метод используется мы можем получить результат как немедленно, так и в момент, когда данные запроса будут действительно нам необходимы, например, при попытке перебора элементов последовательности в цикле.
Отложенное выполнение запросов LINQ
Отложенное выполнение означает, что операция LINQ не выполняется в той точке кода, где объявлен запрос. Результаты выполнения отложенного запроса зависят от содержимого источника данных при выполнении запроса, а не при его определении. К методам, использующим отложенное выполнение относятся практически все методы, которые возвращают значения типа IEnumerable<T>
или IOrderedEnumerable<TElement>
. Одним из методов, использующих отложенное выполнение является метод Where
. Рассмотрим следующий пример:
List<int> ints = new List<int> { 1, 4, 5, 6, 8, 10, 15, 16, 9 }; var data = ints.Where(s => s > 9);//выбираем все числа больше 9. В этой точке запрос НЕ выполняется ints.Add(55); foreach (int value in data) //запрос выполнится здесь Console.WriteLine(value);
Так как метод Where
использует отложенное выполнение, то при вызове метода мы создаем сам запрос на получение всех чисел больше 9, но фактически его не выполняем. Выполнение запроса происходит в тот момент, когда мы пытаемся перебрать элементы полученной последовательности в цикле foreach
. Убедиться в этом можно, если посмотреть на результат работы приложения:
15
16
55
Таким образом, можно сказать, что отложенное выполнение запросов LINQ позволяет, при необходимости, повторно использовать запросы к источнику данных и создавать сложные запросы в несколько шагов.
Немедленное выполнение запросов LINQ
Немедленное выполнение запросов LINQ подразумевает получение результата в точке кода где вызывается запрос. К методам, использующим немедленное выполнение относятся все методы LINQ возвращающее скалярное значение (Sum
, Count
и т.д.), а также методы преобразования данных. Например, чтобы получить результат Where
из предыдущего примера немедленно, мы могли бы сделать так:
List<int> ints = new List<int> { 1, 4, 5, 6, 8, 10, 15, 16, 9 }; var data = ints.Where(s => s > 9) .ToArray(); //вызовет немедленное выполнение запроса Where ints.Add(55); foreach (int value in data) //запрос выполнится здесь Console.WriteLine(value);
В этом случае, результат будет следующим:
15
16
Список методов, использующих отложенное и немедленное выполнение можно посмотреть в справочнике.
Итого
Все методы LINQ по способу выполнения можно разделить на две группы — с отложенным выполнением и немедленным выполнением. Отложенное выполнение запроса LINQ подразумевает получение результата запроса в тот момент, когда это необходимо, например, при переборе элементов последовательности в цикле или запросе очередного элемента через итератор последовательности.