2011-05-03 46 views
0

女巫的做法是更好的,或什麼是這樣做的更好的辦法:Foreach循環使用LINQ語句的性能

Stuffs[] stuffs = getStuffs(); 
    1) 

    foreach (var stuff in stuffs.Where(x => x.StartDate <= DateTime.Now.AddDays(-1) && x.EndDate != DateTime.MinValue)) 
    { 
    } 

    2) 
    foreach (var stuff in stuffs.Where(x => x.StartDate <= DateTime.Now.AddDays(-1) && x.EndDate != DateTime.MinValue).ToList()) 
    { 
    } 

    3) 
    stuffs = stuffs.Where(x => x.StartDate <= DateTime.Now.AddDays(-1) && x.EndDate != DateTime.MinValue).ToArray(); 
    foreach (var stuff in stuffs) 
    { 

    } 

我覺得數字3是獲得更好的性能。還有什麼想法?

回答

2

一般:措施!

出於可讀性我說的1的混合和3.該長在foreach代碼變得有點不可讀的頭部直接一條線,所以我把該查詢在上面的單獨的行循環:

var stuffs = from x in getStuffs() 
      where x.StartDate <= DateTime.Now.AddDays(-1) && 
        x.EndDate != DateTime.MinValue 
      select x; 

var stuffs = getStuffs().Where(x => x.StartDate <= DateTime.Now.AddDays(-1) && x.EndDate != DateTime.MinValue); 

但是你的願望。但在那之後,使用普通的foreach循環:

foreach (var s in stuffs) { 
} 

也沒有必要轉換成一個列表,因爲foreach可以遍歷可迭代的集合,包括LINQ的懶惰評價的東西。轉換到列表可能實際上費用你的時間。如果您需要在之前評估循環,但您可能需要這樣做,但這並不是一個普遍的需求(以我的經驗)。

+0

感謝您的解釋 – 2011-05-03 06:22:11

2

你應該檢查,但通常獲取的數據和你在循環中執行的操作不僅僅是迭代。第一個應該更快,因爲你沒有創建一個新的列表,你不需要在這裏。
我也建議將DateTime.Now.AddDays(-1)置於一個變量中 - 除了possible speed benefits之外,它的值在迭代期間可能會改變,這可能會影響程序的正確性。

+0

對'DateTime.Now'事物的良好調用。 – Joey 2011-05-03 05:14:24

0

第一個通常是最好的表現。它將在您循環時過濾數據,因此它不會爲列表或數組分配空間來容納所有項目。

第二和第三個表現幾乎相同。它們都過濾數據並將結果放入數組,並在需要時通過複製到新數組來生長數組。

第三種方法也用過濾數據數組替換原始數據,如果稍後使用數據,這將是相關的。另外,這樣做會釋放原始數據,以便在需要時可以進行垃圾回收,這對於源數組非常龐大的特殊情況下的性能可能會更好,並且如果您在代碼中使用了大量內存在循環內。

如果比較選項之間的速度,則不會看到太多差異。分配數組並不需要太多時間,但稍後它將產生一個小的影響,因爲它們必須最終被垃圾收集。