更改枚举项不会在原始 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 通过 ToList
或 ToArray
结果时,您正在循环 具体集合 ,您对基础对象的更改将持续存在。
我注意到枚举集合的问题是 .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 通过 ToList
或 ToArray
结果时,您正在循环 具体集合 ,您对基础对象的更改将持续存在。