Изменение перечисленных элементов не изменяется в исходном IEnumerable - PullRequest
0 голосов
/ 09 мая 2018

Я заметил проблему с перечислением по коллекции, которая была результатом .Select<T>() Я могу перечислить по ней и изменить каждый элемент в коллекции. Когда я смотрю на коллекцию после того, как перечисление завершено, каждый элемент остается неизменным.

public class FooModel
{
    public Guid? Id { get; set; }
}

[TestClass]
public class UnitTest1
{
    [TestMethod]
    public void TestMethod1()
    {
        IEnumerable<FooModel> foos = Enumerable.Range(0, 100)
            .Select(m => new FooModel());

        foreach(FooModel f in foos)
        {
            f.Id = Guid.NewGuid();
        }

        Assert.IsTrue(foos.All(foo => foo.Id.HasValue));
    }
}

Если я добавлю .ToList() или .ToArray() для выполнения перечислимого, то он изменяет элементы в коллекции.

Я понимаю, что IEnumerable не выполняется после .Select<T>, но когда foreach запускается, он создает перечислитель и выполняет IEnumerable в локальном поле foo. Почему он не ссылается на тот же объект, который создает Select<T>?

Я видел вопросы о том, когда использовать IEnumerable вместо List, но я понимаю разницу между ними. Описание против реализации более или менее. Мой вопрос больше касается того, почему foreach над локальным полем выполняет IEnumerable и не работает с теми же объектами, на которые ссылается локальная переменная.

1 Ответ

0 голосов
/ 09 мая 2018

Почему он не ссылается на тот же объект, который создает Select?

Поскольку foo использует Enumerable.Range, который перечисляет на лету. Нет базового хранилища данных, которое вы перебираете.

Когда вы вызываете foreach, вы выполняете базовый запрос, который на лету создает 100 FooModel объектов, которые вы модифицируете.

Когда вы вызываете .All, вы снова выполняете запрос, который создает еще один 100 Foo объектов на лету , которые не были изменены.

Когда вы увлажняете результаты с помощью ToList или ToArray, вы затем зацикливаетесь на бетонной коллекции , и ваши изменения в базовых объектах будут сохраняться.

...