Подтвердить что ты не робот

Почему я не могу установить свойства переменных итерации в цикле foreach?

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

Я ожидал, что указанная выше строка вернет true. Почему я не могу установить свойства переменных итерации внутри цикла foreach?

4b9b3361

Ответ 1

people - это определение запроса с отсроченным исполнением. Ваш foreach по запросу не имеет значения, это не о невозможности установить свойство. Когда вы вызываете First(), вы снова запускаете запрос.

Чтобы быть ясным, определение запроса здесь состоит в том, что для элементов в числах создайте нового Person и присвойте значение текущего элемента элемента свойству Person Name. Когда вы выполняете итерацию в цикле foreach, запрос оценивается, и вы создаете новые объекты Person. Но те объекты Person не входят в запрос, это просто определение! Выполнение запроса снова выполняет определение снова, создавая разные объекты Person. Тот факт, что вы изменили исходные результаты запроса, не влияет на второй набор результатов.

Если вы хотите выполнить немедленное выполнение, используйте

var people = numbers.Select(n => new Person() 
    { 
        Name = n.ToString() 
    }).ToList(); 

Вы найдете свои изменения в цикле, потому что теперь people - это конкретный список, а не определение запроса.

foreach (var person in people) 
{ 
     person.Name = newName; 
} 

Debug.WriteLine(people.First().Name.Equals(newName)); // returns true

Ответ 2

Это прекрасный пример отложенного исполнения.

Если вы попробуете этот пример, он работает так, как вы ожидаете, так как ToList выполняет запрос.

    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;