Как работает следующая инструкция 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);
}