2012-04-16 70 views
12

我可以看到爲什麼這是不允許的:刪除與LINQ裏面的foreach那裏

foreach (Thing t in myCollection) { 
    if (shouldDelete(t) { 
     myCollection.Delete(t); 
    } 
} 

但這個怎麼樣?

foreach (Thing t in myCollection.Where(o=>shouldDelete(o)) { 
    myCollection.Delete(t); 
} 

我不明白爲什麼會失敗。 「Where()」方法顯然不會返回原始集合,因此當我嘗試從其中刪除某些內容時,我並未列舉原始集合。

+0

有件事我不明白這個「物」的東西。它當然不是內置類型的東西嗎?有人開導我.... – Deb 2012-04-19 01:54:10

+0

對不起,如果問題很混亂。事情可以是任何類,myCollecion是任何ICollection 。 FWIW埃裏克已經完全理解並回答了我的原始問題,因此就我而言,它已關閉。 – Andy 2012-04-19 07:35:18

回答

26

我不明白爲什麼會失敗。

我假設你的問題是「爲什麼這會失敗?」 (你忘了真正問你的問題的問題。)

「在哪裏()」方法,顯然沒有返回原來的集合

正確的。 「Where」返回代表集合的一個IEnumerable<T>,並在其上放置過濾器。

因此,當我試圖從中刪除某些東西時,我並未列舉原始集合。

不正確。你枚舉原始集合。您正在枚舉原始集合,其上放置了一個過濾器

當您調用「Where」時,它不會熱切評估過濾器,並生成一個原始集合的全新副本,並應用過濾器。相反,它會爲您提供枚舉原始集合的對象,但會跳過與篩選器不匹配的項目。

當你在一家商店並且你說「給我看一切」時,向你展示一切的人會向你展示一切。當你說「現在只是給我看一公斤的蘋果,價格在1美元到5美元之間」時,你並沒有構建一個只有蘋果的全新商店。您正在查看與以前完全相同的內容,只需使用過濾器即可。

2

這是因爲收集不應該用foreach循環修改。它試圖在整個foreach循環執行之前刪除它。因此它會失敗。

+1

我覺得你已經接近你答案的第二部分了......你在尋找懶惰的評價嗎? – 2012-04-16 13:14:33

6

第二條語句返回在您的列表上運行的IEnumerable<>。這一次應該沒問題:

foreach (Thing t in myCollection.Where(o=>shouldDelete(o).ToList()) { 
    myCollection.Delete(t); 
} 
+0

+1提了IEnumerable – 2012-04-16 13:23:28

+0

謝謝,這是我已經實現瞭解決方案,但我埃裏克標記爲答案,因爲我真正想要的是要知道發生了什麼事下方 – Andy 2012-04-16 14:26:44

12

嘗試使用此代碼

myCollection.RemoveAll(x => x.shouldDelete(x)); 
9

你可以這樣做:

myCollection.RemoveAll(shouldDelete); 
+0

謝謝,其實我是做別的事情的循環中所以Likurg的建議是爲我好,但我有+1了:-) – Andy 2012-04-16 14:24:47

+2

...如果類型'myCollection'有RemoveAll方法! '列表'確實如此,但許多集合類型都沒有。 – phoog 2012-04-16 22:02:17

1

凡擴展方法篩選基礎上,通過謂詞的收藏價值和返回的IEnumerable 。因此在迭代時不能修改集合。

您可以使用RemoveAll()來達到您的目的。