2012-05-19 71 views
0

我需要改變列表中的項目使用嵌套的/ foreach循環。 問題是,我無法使用帶有或不帶點表示法的LINQ工作。 傳統的方式工作,是這樣的:嵌套的foreach改變列表項

foreach (MapObjectLayer mapObjectLayer in map.Objects) 
{ 
    foreach (MapObject mapObject in mapObjectLayer.MapObjects) 
    { 
     for (int i = 0; i < mapObject.Points.Count; i++) 
     { 
      mapObject.Points[i] = new Vector2(
       mapObject.Points[i].X * map.Scale, 
       mapObject.Points[i].Y * map.Scale); 
     } 
    } 
} 

使用LINQ,這個失敗:

var test = (from mol in map.Objects 
      from mo in mol.MapObjects 
      from p in mo.Points 
      select p).ToList(); 

for (int i = 0; i < test.Count(); i++) 
{ 
    test[i] = new Vector2(
     test[i].X * map.Scale, 
     test[i].Y * map.Scale); 
} 

這失敗:

map.Objects.ForEach(l => l.MapObjects.ForEach(t => t.Points.ForEach(p => p = p * map.Scale))); 

如果我能得到點符號變種工作我會很高興,但我不知道爲什麼它失敗。 使用調試器很明顯,通過檢查點列表可以看出,使用兩個LINQ變量,矢量沒有相乘。

更新:Vector2是一個結構

更新:這裏是兩個單行,我發現(工作的):

map.Objects.SelectMany(m => m.MapObjects).ToList().ForEach(o => o.Points = o.Points.Select(p => p * 2).ToList()); 
map.Objects.ForEach(l => l.MapObjects.ForEach(t => t.Points = t.Points.Select(p => p * 2).ToList())); 
+1

爲什麼你需要將它轉換爲LINQ? – undefined

+3

你爲什麼要使用LINQ? LINQ用於*查詢*,而不是*更新*。 –

+0

我認爲LINQ實際上可能會變慢,您是否在尋找一個「很酷的單線程」? –

回答

2

常規foreach是最好的方式。 LINQ是專爲查詢而設計的。你可以在一行中完成,但它不會優雅或可讀。這裏是如何:

map.Objects.ForEach(l => l.MapObjects.ForEach(t => Enumerable.Range(0, t.Points.Count).ToList().ForEach(i => t.Points[i] *= map.Scale))); 

,你的版本沒有工作的原因是因爲Vector2是值類型。在查詢中,它的值被複制,所以當你做p => p = ...時,你正在分配一個變量的副本。

使用的原代碼。 LINQ不是循環的替代品。

+0

這很好地回答了我的問題,謝謝你的單行:)我陷入了一片混亂,我可能會用這個/ foreach循環來表示這個,謝謝。 –

+0

如果回答您的問題,請將其標記爲答案。 –

+0

完成,但您在Enumerable.Range(0,t.Points.Count)和.ForEach函數之間缺少.ToList()(否則它不會編譯)。 –

1

您可以使用LINQ以及收集物品(其實ReSharper的將提供從嵌套的foreach到LINQ一個重構),但你必須照顧你收集什麼,你更新。

最初的LINQ查詢語法示例收集點的副本到一個新的列表,然後更換新列表的每個元素與Vector2的新實例。即使Vector2是參考類型,只有新列表纔會改變,而不是原始地圖。對象 - 子結構。

它的工作,你所希望的方式,如果

    您參考,而不是值類型和
  • 你指定INSTEAD-OF-Vector2項目的性質工作

  • test [i] .X * = map.Scale