繁体   English   中英

为什么我不能在for循环中更改linq IEnumerable中的元素?

[英]Why can't I change elements from a linq IEnumerable in a for loop?

昨天我写了下面的c#代码(为了易读性而缩短了一点):

 var timeObjects = ( from obj in someList
                     where ( obj.StartTime != null )
                     select new MyObject()
                     {
                        StartTime= obj.StartTime.Value,
                        EndTime = obj.EndTime
                     } )

因此每个项目都有一个startTime,有些项目有一个EndTime(其他项目有null作为EndTime)。

如果已知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 ,因此对临时对象进行了更改。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM