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

时间:2018-05-08 22:17:13

标签: c# .net 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的问题,但我理解两者之间的区别。描述vs或多或少地实施。我的问题更多的是关于为什么foreach超过本地字段,执行IEnumerable并且不对局部变量中引用的相同对象进行操作。

1 个答案:

答案 0 :(得分:2)

  

为什么它不引用Select创建的同一个对象?

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

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

当您致电.All时,您再次执行查询,这会创建另一个 100 Foo对象即时但尚未修改

当您通过ToListToArray 水合结果时,您将循环遍历具体集合,并对基础更改对象将持续存在。