When creating new objects in a LINQ statement, for example:
var list = new List<string>() { "a", "b", "c" };
var created = from i in list select new A();
With class A looking like this:
class A
{
public string Label;
}
And then modifying properties in A with a foreach loop:
foreach (var c in created) {
c.Label = "Set";
}
Why are the values not set when accessing the objects in the IEnumerable
afterwards. E.g. the following assertion fails:
Assert.AreEqual("Set", created.ElementAt(2).Label);
I wonder why this happens. I would expect the foreach-statement to execute the query, and trigger the creation of the objects. MSDN documentation states: "Execution of the query is deferred until the query variable is iterated over in a foreach or For Each loop".
I have reproduced this behavior with .NET 4.5 and Mono 3.2.0. Calling ToList
on the IEnumerable
before accessing the created object makes this problem go away.
It's happening because created
is a query, not a result. So, every time you enumerate it, you're evaluating the Select
over again from scratch.
If you want this to work, make created
an actual list, rather than just an IEnumerable
representing a query.
For example, add:
created = created.ToList();
You say:
I would expect the foreach-statement to execute the query, and trigger the creation of the objects
This is exactly what is happening. The problem is the creation of the objects happens every time you iterate over created
, not just the first time. Since the ElementAt()
method iterates over created
, it's just creating new A
s again.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With