Как работает следующая инструкция 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
из-за отложенного исполнения.
Запрос фактически выполняется, когда переменная запроса повторяется, а не при создании переменной запроса. Это называется отложенным исполнением.
- Suprotim Agarwal, "Отложенное и немедленное выполнение запроса в LINQ"
Существует другое исполнение под названием Выполнение немедленного выполнения запросов, которое полезно для кеширования результатов запроса. От Suprotim Agarwal снова:
Чтобы принудительно выполнить запрос, который не создает одноэлементное значение, вы можете вызвать метод
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);
}
Это произошло из-за отложенного выполнения, что означает, что вычисление выражения не выполняется до тех пор, пока оно не понадобится где-то. Это улучшает производительность, если данные слишком велики.
Причиной этого является отсроченное выполнение вашего лямбда-выражения. Запрос запускается при запуске итерации в цикле foreach.
Когда вы используете IEnumerable < > , полученный из LINQ, создается только класс Enumerator, и итерация запускается только тогда, когда вы используете его в некоторой прогулке.
Вы получаете этот результат из-за отложенного выполнения, что означает, что результат фактически не оценивается до момента его первого доступа.
Чтобы сделать его более понятным, просто добавьте 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);
}