首页 > 解决方案 > 更改枚举项在原始 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>创建的相同对象?

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

标签: c#.netienumerable

解决方案


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

因为foo正在使用Enumerable.Rangewhich enumerates on-the-fly。没有您要迭代的基础数据存储。

当您调用时,foreach您正在执行底层查询,它会动态创建 100 个FooModel对象,您可以对其进行修改。

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

当您通过or对结果进行水合时,您将循环一个具体的集合,并且您对基础对象的更改将持续存在。ToListToArray


推荐阅读