2016-11-16 32 views
0

我有一個項目列表,我想遍歷它們的一個子集。現在,我想知道在從列表中刪除不需要的項目之間是否存在性能影響差異,然後通過它循環;或者只是在for循環中過濾列表。.RemoveAll和.Where之間的性能差異在C#中

這裏是一個例子。

的removeall過的做法:

list.RemoveAll(o => !someOtherList.Contains(o.Property)); 

foreach (var i in list) 
{ 
} 

在哪裏做法:

foreach (var i in list.Where(o => someOtherList.Contains(o.Property)) 
{ 
} 

據我所知,第一種方法實際上是要處理的是在列表,作爲第二個則不會。這並不是真的關心我。我更關心的是第二種方法中的過濾器是否應用於每次迭代,或者C#是否足夠聰明以創建子集並且僅循環該子集(幾乎就像使用臨時變量的第一種方法)。

+0

如果您的問題歸結爲「someOtherList.Contains'會被調用多少次?」,我強烈懷疑這兩個示例的答案是相同的。 –

+2

哪一個更快?運行兩次1000次並計算平均值! – user3185569

+0

@Damien_The_Unbeliever:我的問題歸結爲多少次list.Where將被調用。 – Johannes

回答

5

我更關注是否適用於每個迭代還是C#是足夠聰明的創建通過該子集(幾乎像第一 方法有 子集,僅環在第二種方法過濾 一個臨時變量)

Linq的Where使用yield爲了一次返回一個元素一次請求。

因此,實際上什麼是在第二種方法做的是:

1迭代通過列表

2-檢查當前的元素相匹配的條件(遍歷someOtherList,除非它是一個特殊的查找數據結構如。HashSet

3-一旦我們找到的第一個元素返回它

4-執行的foreach體邏輯

5繼續從那裏我們停在第3步

含義搜索,如果你決定基於在foreach塊內部的一些條件打破,那麼也許不是所有的列表可以在該點進行掃描,其在某些情況下,可能會在大型列表上提升性能。

+0

謝謝,這很好地解釋了它。 – Johannes

1

作爲對其他人已經說過的內容的補充,如果循環操作與您所展示的一樣,使用原始性能不會有可忽略的差異。

但是,第一個需要具有物化列表,而後者需要IEnumerable。另外,爲了循環內容的運行,首先需要首先實現,直到那時循環內容沒有開始完成。使用NOP循環的IOW可能需要大約10秒才能完成某個列表和另一個列表。當循環中有一些工作(可能),那麼第一個在進入循環之前花費10秒,那麼你需要循環處理的時間。後者OTOH將直接針對找到的每個元素進行循環。如果循環內容是一個耗時的操作,而且可以做到異步,那麼後者將是一個明顯的贏家。

相關問題