簡體   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