string newName = "new name";
int[] numbers = new int[] { 1, 2, 3 };
var people = numbers.Select(n => new Person()
{
Name = n.ToString()
});
foreach (var person in people)
{
person.Name = newName;
}
Debug.WriteLine(people.First().Name == newName); // returns false
I expected the above line to return true. Why can't I set properties of iteration variables inside a foreach loop?
people
is a query definition with deferred execution. Your foreach over the query is irrelevant, this isn't about an inability to set a property. When you invoke First()
, you run the query again.
To be clear, the query definition here is that for the elements in numbers, create a new Person and assign the value of the current number element to the Person's Name property. When you iterate in the foreach loop, the query evaluates, and you create new Person objects. But those Person objects are not in the query, it's just a definition! Running the query again executes the definition again, creating different Person objects. The fact that you modified the query's original results does not impact the second set of results.
If you would like an immediate execution, use
var people = numbers.Select(n => new Person()
{
Name = n.ToString()
}).ToList();
You'll find your changes in the loop sticking, because now people
is a concrete list instead of a query definition.
foreach (var person in people)
{
person.Name = newName;
}
Debug.WriteLine(people.First().Name.Equals(newName)); // returns true
This is a perfect example of deferred execution.
If you try this example it works as you expect since the ToList
executes the query.
string newName = "new name";
int[] numbers = new int[] { 1, 2, 3 };
var people = numbers.Select(n => new Person()
{
Name = n.ToString()
}).ToList(); // <===== here
foreach (var person in people)
{
person.Name = newName;
}
var b = people.First().Name == newName;
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