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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With