2011-07-17 32 views
1

當我構建以下代碼時,出現錯誤Cannot modify members of 'pd' because it is a 'foreach iteration variable'如何在LINQ中重寫C#foreach

foreach (var w in tt.Weeks) 
    foreach (var d in w.Days) 
    foreach (var pd in d.Periods) 
     if (pd.Type == TimetablePeriod.Types.Registration) pd.ClassId = clsId; 

我明白爲什麼會出現這個錯誤,但我試圖想出一個很好的方法來重寫代碼。我可以使用嵌套for循環,但有沒有一個很好的LINQ解決方案?

(如果現在還不清楚,我正在嘗試設置各個時期的ClassId所有周的所有天clsId,無論在PeriodTypeTimetablePeriod.Types.Registration。)

+5

'pd'是一個可變結構嗎?用這個代碼應該編譯一個類。 – CodesInChaos

+0

這是一個結構,但ClassId有一個公共setter,所以肯定會沒事的? – James

+2

你需要使用'for'。或者用一個類替換你的結構。 – CodesInChaos

回答

6

我假設你有一個struct這樣的:

public struct Period 
{ 
    public SomeType ClassId{get;set;} 
} 

這意味着,在使用LINQ兩種或foreach收集任何迭代將對該值的拷貝工作。所以如果你修改它們,你只能修改一個臨時的副本,然後將被丟棄。原始結構將保持不變。

由於這個和其他許多原因,除非你有充分的理由使用它們,否則應該避免使用可變結構。 (搜索「可變結構邪惡」,你會發現很多)

在你的情況下,你可以簡單地用類替換struct。然後你得到引用語義。

或者你可以使用for循環,它可以讓你直接訪問。但它仍然不會編譯與天真實施:

for(int i=i;i<list.Count;i++) 
    list[i].ClassId=something; 

因爲列表上的索引器是一個屬性,它複製其結果。有了數組,這可以工作,因爲數組的索引器返回一個託管引用(或類似的東西)。對於你需要做的列表:

for(int i=i;i<list.Count;i++) 
{ 
    var copy=list[i]; 
    copy.ClassId=something; 
    list[i]=copy; 
} 
+0

+1:非常尖銳的一點! –

1

請嘗試以下代碼。

您提到的問題與代碼是否爲LINQ或不相關,如@CodeInChaos所述。由於pd是Struct類型,您需要替換它以設置值(clsId)。

foreach (var w in tt.Weeks) 
{ 
    foreach (var d in w.Days) 
    { 
     for (int i = 0; i < d.Periods.Count; i++) 
     { 
      if (d.Periods[i].Type == TimetablePeriod.Types.Registration) 
       d.Periods[i] = new Period(clsId, ....); 
     } 
    } 
}