Как работает следующий оператор LINQ ?
Вот мой код:
var list = new List<int>{1,2,4,5,6};
var even = list.Where(m => m%2 == 0);
list.Add(8);
foreach (var i in even)
{
Console.WriteLine(i);
}
Вывод: 2, 4, 6, 8
Почему нет 2, 4, 6
?
Как работает следующий оператор LINQ ?
Вот мой код:
var list = new List<int>{1,2,4,5,6};
var even = list.Where(m => m%2 == 0);
list.Add(8);
foreach (var i in even)
{
Console.WriteLine(i);
}
Вывод: 2, 4, 6, 8
Почему нет 2, 4, 6
?
Ответы:
Выход 2,4,6,8
из-за отложенного выполнения .
Запрос фактически выполняется, когда переменная запроса перебирается, а не когда переменная запроса создается. Это называется отложенным исполнением.
- Супротим Агарвал, «Отложенное и немедленное выполнение запросов в LINQ»
Существует еще одно выполнение, называемое Immediate Query Execution , которое полезно для кэширования результатов запросов. Из Супротима снова Агарвал:
Чтобы принудительно выполнить запрос, который не выдает одноэлементное значение, можно вызвать метод
ToList(), ToDictionary(), ToArray(), Count(), Average()
илиMax()
для запроса или переменной запроса. Это так называемые операторы преобразования, которые позволяют вам сделать копию / снимок результата и получить доступ столько раз, сколько вам нужно, без необходимости повторного выполнения запроса.
Если вы хотите, чтобы вывод был 2,4,6
, используйте .ToList()
:
var list = new List<int>{1,2,4,5,6};
var even = list.Where(m => m%2 == 0).ToList();
list.Add(8);
foreach (var i in even)
{
Console.WriteLine(i);
}
.First()
, .FirstOrDefault()
, .Single()
а .SingleOrDefault()
также вызвать вычисления запроса.
Это произошло из-за отложенного выполнения, что означает, что вычисление выражения не выполняется, пока оно не понадобится где-то. Это повышает производительность, если данные слишком велики.
Причиной этого является отложенное выполнение вашего лямбда-выражения. Запрос выполняется, когда вы начинаете итерацию в цикле foreach.
Вы получаете этот результат из-за отложенного выполнения, что означает, что результат фактически не оценивается до его первого доступа.
Чтобы сделать это более понятным, просто добавьте 10 к списку в конце вашего фрагмента и затем напечатайте снова, вы не получите 10 в выводе
var list = new List<int>{1,2,4,5,6};
var even = list.Where(m => m%2 == 0).Tolist();
list.Add(8);
foreach (var i in even)
{
Console.WriteLine(i);
}
//new*
list.Add(10);
foreach (var i in even)
{
Console.WriteLine(i);
}
10
в выходной.
8
ни в одном выводе.