Вызывается ли Linq-Query toList(), генерируя копии содержащихся элементов?
Я столкнулся с (для меня) странным поведением. Вот код:
var objects = from i in items
//some calculations
select something;
// other calculations
objects.ToList().ForEach(x => {
//some calculations
x.Property = "some text"
});
return objects;
Сначала я генерирую IEnumerable
Это запрос к БД, я пропустил детали. Затем я должен сделать другие вычисления и в конце я перебрать свои объекты, чтобы установить дополнительный параметр. Запуск этого кода, как только IEnumerable
объекты возвращаются, их Property
не установлен.
В противном случае, если я перееду ToList()
в последующем выражении Linq Property
установлено:
var objects = (from i in items
//some calculations
select something).ToList();
// other calculations
objects.ForEach(x => {
//some calculations
x.Property = "some text"
});
return objects;
Насколько я знаю, объекты не копируются, а ссылаются... верно? Что за очевидными кодами происходит? В чем разница?
2 ответа
Помните, что запрос Linq - это просто запрос - он говорит: "если я запрашиваю эти данные, вот что я хочу_. Он не содержит никаких данных, но ожидает, пока вы не запросите_ результатов (через foreach
, ToList
, ToArray
, так далее.)
Разница в том, что вы не захватываете список, возвращенный ToList
в первом примере. Используется ForEach
позвони но objects
переменная по-прежнему содержит ссылку на исходный запрос. Когда вы просите об этом снова - он снова получает данные. Когда он снова получает данные, создаются новые объекты.
Так что в этом отношении - да ToList()
создает новый список. Он не изменяет вызываемый объект, чтобы превратить его в список.
Во втором примере objects
переменная содержит ссылку на список, сгенерированный из запроса через ToList()
, поэтому, когда вы изменяете их и возвращаете objects
вы возвращаете тот же список.
В вашем первом примере кода objects.ToList()
на самом деле создает новый объект типа List
ты работаешь со своим ForEach
, После ForEach
сделано, вы все еще только возвращаете IEnumerable
и список, который вы на самом деле хотели вернуть, исчезнет.
Назначая запрос LINQ с помощью ToList()
к object
переменная, вы используете недавно созданный список в вашем ForEach
,