2010-02-03 62 views
8

我正在考慮一個重新因素,但我不知道最終結果是否只是矯枉過正。 目前我有正在使用linq在這種情況下過度殺傷

IList<myobjecttypebase> m_items; 

    public int GetIncrementTotal() 
    { 
    int incrementTot; 
    foreach(myobjecttypebase x in m_items) 
    { incrementTot += x.GetIncrement(); } 
    } 

難道是矯枉過正和/或低效率使用LINQ對foreach

m_items.ToList().ForEach(x => incrementTot += x.GetIncrement()); 

會投是一個顯著的開銷嗎?

回答

4

的ToList方法是使用LINQ擴展方法,但該方法的ForEach只是一種方法在List類中。

這裏主要的開銷是對ToList方法的調用,它從集合中創建一個新的List。 ForEach也有輕微的開銷,因爲它必須爲每個項目調用一個委託。

如果你想使用LINQ方法,總結方法似乎更爲合適:

public int GetIncrementTotal() { 
    return m_items.Aggregate(0, (t, i) => t + i.GetIncrement()); 
} 

或款項:

public int GetIncrementTotal() { 
    return m_items.Sum(i => i.GetIncrement()); 
} 

要麼有超過您最初的版本有輕微的開銷,所以如果你想最高效的,只是堅持一個簡單的循環。

+0

感謝您的全面解答Guffa。 – Andrew 2010-02-03 11:13:57

+0

這裏的「輕微開銷」只是調用代理和內聯代碼之間的區別。除非集合很大,否則你將許多集合加起來作爲編碼選擇的基礎,因此屬於過早優化領域。只有在性能測試顯示您的總運行時間得到顯着改善時才進行此類更改。 – Richard 2010-02-03 12:01:13

3

開銷將在迭代集合兩次。

m_items.ToList() // First iteration to add to the list all the items 
    .ForEach(x => incrementTot += x.GetIncrement()); /* Second iteration to 
                 perform logic */ 

ToList不執行,大多數LINQ語句慵懶地迭代,爲此它會迫使代碼遍歷集合的兩倍。

一般而言,LINQ表單看起來更好看,但如果您擔心性能問題,最好避免使用它。

+0

我假設linq版本將是開銷的一個版本。如果是這樣,爲什麼ToList()方法需要遍歷枚舉來從IList中投射 – Andrew 2010-02-03 10:58:20

+0

@Andrew - 因爲它需要將集合轉換爲列表。 – Oded 2010-02-03 10:59:27

+0

@Andrew:ToList()方法不是強制轉換。這是一種轉換方法,將分配和填充新的List <>對象。 – 2010-02-03 11:00:34

7

爲什麼不直接在IList上使用SUM運算符?

它使用Func代表有幾個重載:

m_items.Sum(x => x.GetIncrement()); 
+0

GetIncrement方法是基類上的抽象方法,不同的具體實現會覆蓋增量值。否則,我將只使用IList上的.Count() – Andrew 2010-02-03 11:00:37

+0

不會更改答案... – Oded 2010-02-03 11:03:55

+0

由於下面的John代碼示例,我明白了您的觀點。 – Andrew 2010-02-03 11:05:02

1

不要做這種方式。
ToList()這裏將分配和填充一個新的列表,恕我直言,沒有必要。 儘管編寫一個ForEach擴展方法來迭代實現IEnumberable的任何對象是一個簡單的練習,但我建議不要這樣做(請參閱Eric Lippert的文章foreach V's ForEach)。

我會去與foreach。

P.S.你需要初始化incrementTot(對不起,我不能幫助我自己)

2

如俄德提到,在使用SUM

incrementTot = m_items.ToList().Sum(x => x.GetIncrement()); 
+2

爲什麼打算創建一個列表,如果你所要做的就是總結這些值? – 2010-02-03 11:03:23

+0

謝謝你的例子。我沒有得到Oded的意思,因爲我對linq比較陌生。 – Andrew 2010-02-03 11:03:40

+0

喬恩斯威特一度適合。 ToList是多餘的。 – 2010-02-03 11:50:35

3

ForEach不是LINQ的一部分 - 這是List<T> API的一部分,一直以來。 NET 2.0。

它不是LINQ的一部分的原因是它是一種自然而然的副作用方法...和LINQ不鼓勵副作用。

使用金額是正確的解決方案在這裏,但你並不需要首先創建一個列表:

return m_items.Sum(x => x.GetIncrement());