我注意到枚举一个集合的问题,该集合是.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并且不对局部变量中引用的相同对象进行操作。
答案 0 :(得分:2)
为什么它不引用Select创建的同一个对象?
因为foo
正在使用Enumerable.Range
,它会即时枚举。您没有迭代的基础数据存储。
当你调用foreach
时,你正在执行基础查询,它会动态创建100个FooModel
个对象,你可以修改它们。
当您致电.All
时,您再次执行查询,这会创建另一个 100 Foo
对象即时但尚未修改
当您通过ToList
或ToArray
水合结果时,您将循环遍历具体集合,并对基础更改对象将持续存在。