更改枚举项不会在原始 IEnumerable 中更改

Changing Enumerated items aren't changed in original IEnumerable

我注意到枚举集合的问题是 .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 运行时它会创建一个枚举器并在 foo 本地字段上执行 IEnumerable。为什么它不引用 Select<T> 创建的同一个对象?

我看到过关于何时使用 IEnumerable 而不是 List 的问题,但我了解两者之间的区别。描述与实施或多或少。我的问题更多是关于为什么 foreach 在局部字段上执行 IEnumerable 并且不对局部变量中引用的相同对象进行操作。

Why isn't it referencing the same object that the Select creates?

因为 foo 正在使用 Enumerable.Range 即时枚举。没有您正在迭代的基础数据存储。

当您调用 foreach 时,您正在执行基础查询,它动态创建 100 个 FooModel 对象,您可以修改这些对象。

当您调用 .All 时,您再次执行查询,这会创建 另一个 100 Foo 个对象 动态 尚未修改。

当您 hydrate 通过 ToListToArray 结果时,您正在循环 具体集合 ,您对基础对象的更改将持续存在。