Emaborsa
Emaborsa

Reputation: 2860

Is a Linq-Query called toList() generating copies of the contained elements?

I encountered a (for me) strange behaviour. Here is the code:

var objects = from i in items
              //some calculations
              select something;

// other calculations

objects.ToList().ForEach(x => {
    //some calculations
    x.Property = "some text"
});

return objects;

First I generate a IEnumerable, it is a query to the db, I skipped the details. Then I have to do other calculations and at the end I iterate over my objects to set a further parameter. Running this code, once the IEnumerable objects is returned, their Property is not set.

Otherwise if I move the ToList() in the Linq expression as followed, the Property is set:

var objects = (from i in items
              //some calculations
              select something).ToList();

// other calculations

objects.ForEach(x => {
    //some calculations
    x.Property = "some text"
});

return objects;

As far I know, the objects are not copied, but referenced...right? What does behind the apparently codes happen? What is the difference?

Upvotes: 3

Views: 2042

Answers (2)

D Stanley
D Stanley

Reputation: 152566

Remember that a Linq query is just a query - it is saying "if I ask for this data, here's what I want_. It does not hold any data but waits until you ask_ for the results (via foreach, ToList, ToArray, etc.)

The difference is you're not capturing the list returned by ToList in the first example. It's used by the ForEach call but the objects variable still holds a reference to the original query. When you ask for it again - it fetches the data again. When it fetches the data again, new objects are created.

So in that respect - yes ToList() creates a new list. It does not modify the object that it's called on to turn it into a list.

In your second example the objects variable holds a reference to the list generated from the query via ToList(), so when you modify them and return objects you're returning the same list.

Upvotes: 6

Maximilian Riegler
Maximilian Riegler

Reputation: 23506

In your first code sample the objects.ToList() is in fact creating a new object of type List you're working on with your ForEach. After the ForEach is done you're still just returning your IEnumerable and the list you actually wanted to return will be gone.

By assigning the LINQ query with a ToList() to the object variable, you're using the newly created list in your ForEach.

Upvotes: 0

Related Questions