Почему я не могу установить свойства переменных итерации в цикле foreach? - PullRequest
12 голосов
/ 03 февраля 2012
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?

Ответы [ 2 ]

19 голосов
/ 03 февраля 2012

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

Для ясности, определение запроса здесь состоит в том, что для элементов в числах создайте нового человека и присвойте значение текущего элемента числа свойству имени человека. Когда вы выполняете итерацию в цикле 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
6 голосов
/ 03 февраля 2012

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

Если вы попробуете этот пример, он будет работать так, как вы ожидаете, так как 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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...