修改Select<T>生成的IEnumerable枚举项后原集合未变更问题求助
问题原因与解决方案
为什么修改后看不到变化?
这是LINQ的延迟执行特性在搞鬼:
Select<T>()是延迟执行的LINQ方法,它不会立刻生成所有FooModel实例,而是在每次枚举(比如foreach、后续查看集合的操作)时,才会逐个执行new FooModel()创建新对象。- 你第一次
foreach时,确实创建了100个实例并给Id赋值,但当你之后再查看foos时,相当于又一次触发了枚举,这时候Select会重新创建100个全新的FooModel,这些新对象的Id自然还是null。
解决方法
方法1:转换成立即执行的集合(推荐)
用ToList()或ToArray()把延迟执行的IEnumerable转换成实际的集合,这样Select会一次性创建所有实例并存储起来,后续所有操作都是针对同一批对象:
IEnumerable<FooModel> foos = Enumerable.Range(0, 100) .Select(m => new FooModel()) .ToList(); // 立即执行,固化所有实例 foreach(FooModel foo in foos) { foo.Id = Guid.NewGuid(); } // 此时再查看foos,所有Id都已被正确赋值
方法2:把修改逻辑整合到Select中
如果你的场景确实需要保留延迟执行,可以直接在Select的委托里完成对象初始化和赋值:
IEnumerable<FooModel> foos = Enumerable.Range(0, 100) .Select(m => new FooModel { Id = Guid.NewGuid() }); // 每次枚举时都会创建带Id的实例,查看时也能看到正确值
关键知识点总结
- 延迟执行LINQ方法(如
Select、Where、Skip等):不会立即生成结果,仅在枚举时才执行逻辑,每次枚举都会重新执行。 - 立即执行LINQ方法(如
ToList、ToArray、Count、First等):会立刻执行所有逻辑,把结果固化到集合中,后续操作不会重复执行原逻辑。
内容的提问来源于stack exchange,提问作者Johnathon Sullinger
相关产品推荐
相关产品推荐

