为什么我不能在for循环中更改linq IEnumerable中的元素?
昨天我写了下面的c#代码(为了易读性而缩短了一点):
var timeObjects = ( from obj in someList where ( obj.StartTime != null ) select new MyObject() { StartTime= obj.StartTime.Value, EndTime = obj.EndTime } )
因此每个项目都有一个startTime,而另一些项目有一个EndTime(其他项目的尾数为null)。
如果已知start和endtime,我想计算经过的时间:
foreach ( var item in timeObjects) { if ( item.EndTime == null ) { item.elapsed = 0; } else { item.elapsed = ( item.EndTime.Value - item.StartTime).Minutes; } }
但这不起作用! timeObjects集合永远不会改变。
如果我说:
var timeObjects = ( from obj in someList where ( obj.StartTime != null ) select new MyObject() { StartTime= obj.StartTime.Value, EndTime = obj.EndTime } ).ToList(); foreach ( var item in timeObjects) { if ( item.EndTime == null ) { item.elapsed = 0; } else { item.elapsed = ( item.EndTime.Value - item.StartTime).Minutes; } } //(only change is the ToList() at the end of the linq statement)
它确实有效。
我非常想知道为什么会这样?
你的timeObjects
是一个可枚举的延迟执行。 如果对列表进行两次枚举,则实际将对结果进行两次计算,从而创建新对象。
当您执行ToList()时,它创建了该查询/可枚举的结果的本地副本,这就是您看到更改的原因。 这种LINQ查询不会创建任何类型的列表。 在您枚举查询之前,不会执行查询本身。 你在(from … select)状态下所做的就是创建查询定义。
您的原始timeObjects定义定义了一个延迟评估的LINQ表达式,因此每当您尝试遍历timeObjects可枚举时,它将创建MyObject的新实例。
在调用ToList()之前,它似乎不是IEnumerable而是IQueryable ,因此对临时对象进行了更改。