为什么我不能改变从LINQ IEnumerable的元素在for循环? [英] Why can't I change elements from a linq IEnumerable in a for loop?

查看:155
本文介绍了为什么我不能改变从LINQ IEnumerable的元素在for循环?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

昨天我写了下面的C#代码(缩短一点的可读性):

  VAR timeObjects =(从OBJ在someList 
,其中(obj.StartTime!= NULL)
选择新MyObject来()
{
开始时间= obj.StartTime.Value,
结束时间= obj.EndTime
})

因此,每个项目都有一个startTime和一些有一个结束时间(其他有null作为结束时间)。



如果双方开始和结束时间是已知的,我想计算经过时间:

 的foreach(在timeObjects VAR项)
{
如果(item.EndTime == NULL)
{
item.elapsed = 0;
}
,否则
{
item.elapsed =(item.EndTime.Value - item.StartTime).Minutes;
}
}



但是,这并不工作!该timeObjects集合永远不会改变。



如果我说:

  VAR timeObjects =(从obj获得在someList 
,其中(obj.StartTime!= NULL)
选择新MyObject来()
{
开始时间= obj.StartTime.Value,
结束时间= obj.EndTime
}).ToList();

的foreach(在timeObjects VAR项)
{
如果(item.EndTime == NULL)
{
item.elapsed = 0;
}
,否则
{
item.elapsed =(item.EndTime.Value - item.StartTime).Minutes;
}
}
//(唯一的变化是了ToList()在LINQ语句的结束)

它的工作。



我倒是非常想知道这是为什么?

解决方案

你<$ç$ç> timeObjects 是迟execution enumerable。如果枚举列表两次,结果实际上将两次评估,创建新的对象。



当你执行了ToList(),它产生的结果的本地副本该查询/枚举的这就是为什么你看到的变化。这种类型的LINQ查询不会创建任何类型的幕后名单。直到你枚举它不执行查询本身。所有你正在做的(从...选择)状态创建查询定义。


Yesterday I wrote the following c# code (shortened a bit for legibility):

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

So each item has a startTime and some have an EndTime (others have null as EndTime).

If both start and endtime are known I wanted to calculate the elapsed time:

foreach ( var item in timeObjects)
{
    if ( item.EndTime  == null )
    {
      item.elapsed = 0;
    }
    else
    {
      item.elapsed = ( item.EndTime.Value - item.StartTime).Minutes;
    }
}

But this doesn't work! the timeObjects collection never changes.

If I say:

 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)

it does work.

I'd very much like to know why this is?

解决方案

Your timeObjects is a delayed-execution enumerable. If you enumerate over the list twice, the results will actually be evaluated twice, creating new objects.

When you performed ToList(), it created a local copy of the RESULTS of that query/enumerable, which is why you saw the changes. This sort of LINQ query doesn't create any sort of list under the covers. The query itself isn't performed until you enumerate over it. All you're doing in the (from ... select) state is creating the query definition.

这篇关于为什么我不能改变从LINQ IEnumerable的元素在for循环?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆