2009-06-25 181 views

回答

55

編寫最清晰的代碼,然後進行基準測試和配置文件發現任何性能問題。如果您的確實有存在性能問題,您可以嘗試使用不同的代碼來確定是否更快(使用盡可能真實的數據測量所有時間),然後判斷性能改進是否值得可讀性受到打擊。

直接foreach方法在許多情況下比LINQ更快。例如,考慮:

var query = from element in list 
      where element.X > 2 
      where element.Y < 2 
      select element.X + element.Y; 

foreach (var value in query) 
{ 
    Console.WriteLine(value); 
} 

現在有兩個where條款和select條款,所以每一個最終的項目必須經過三個迭代器。 (顯然這兩個where子句可以在這種情況下合併,但我在做一般點)

現在有了直接的代碼進行比較:

foreach (var element in list) 
{ 
    if (element.X > 2 && element.Y < 2) 
    { 
     Console.WriteLine(element.X + element.Y); 
    } 
} 

這將運行得更快,因爲它有更少的籃球穿過。儘管如此,控制檯輸出可能會使迭代器成本變得更低,我當然更喜歡LINQ查詢。

編輯:爲了回答關於「嵌套的foreach」循環通常...那些體表示SelectMany或第二from條款:

var query = from item in firstSequence 
      from nestedItem in item.NestedItems 
      select item.BaseCount + nestedItem.NestedCount; 

這裏我們只需要添加一個額外的迭代,因爲我們」由於嵌套的foreach循環,d已經在第一個序列中的每個項目使用了一個額外的迭代器。還有一些開銷,包括在委託中進行投影的開銷,而不是「內聯」(我之前沒有提到過),但它與嵌套的foreach性能仍然不會有很大的不同。

這並不是說你不能用LINQ拍攝自己的腳,當然。如果你不首先使用你的大腦,那麼你可以寫出效率低下的查詢 - 但這與LINQ的獨特之處不同......

+13

第一句應作爲橫幅打印出來,掛在每個編程部門。 – 2012-11-02 03:18:39

+1

喬恩...你真棒...最衷心的感謝! – 2013-08-22 06:42:50

11

這是比較複雜的。最終,大部分LINQ到對象都是(幕後)一個foreach循環,但增加了一些抽象/迭代器塊/等的額外開銷。但是,除非你在兩個版本中做了非常不同的事情(foreach vs LINQ ),它們都應該是O(N)。

真正的問題是:是否有更好的方式來編寫您的特定的算法,這意味着foreach會效率低下? LINQ可以爲你做嗎?

例如,LINQ可以很容易地散列/分組/排序數據。

22

如果你

foreach(Customer c in Customer) 
{ 
    foreach(Order o in Orders) 
    { 
    //do something with c and o 
    } 
} 

您將執行Customer.Count *訂購。計數迭代


如果你

var query = 
    from c in Customer 
    join o in Orders on c.CustomerID equals o.CustomerID 
    select new {c, o} 

foreach(var x in query) 
{ 
    //do something with x.c and x.o 
} 

您將執行Customer.Count + Order.Count迭代,因爲Enumerable.Join作爲一個HashJoin實現。

+0

很好的解答和很好的解釋 – 2009-06-25 14:39:37

+4

這是因爲你運行兩種不同的算法;你正在比較蘋果和橘子。我不明白這與提出的問題有什麼關係。 – mquander 2009-06-25 14:50:20

2

之前已經說過了,但它值得重複。

開發人員在運行性能測試之前不會知道性能瓶頸的位置。

將技術A與技術B進行比較也是如此。除非存在顯着差異,否則您只需對其進行測試即可。如果你有一個O(n)和O(n^x)的場景,這可能是顯而易見的,但是由於LINQ的東西大部分是編譯器巫術,所以它值得分析。此外,除非您的項目正在生產中,並且您已經對代碼進行了剖析並發現該循環會減慢執行速度,否則請將其作爲您偏好的可讀性和維護的依據。不成熟的優化是魔鬼。

2

一個很大的好處是,使用Linq-To-Objects查詢可以輕鬆將查詢轉換爲PLinq,並讓系統自動對當前系統的正確線程數執行操作。

如果你在大數據集上使用這種技術,這很容易成爲一個很小的麻煩的大贏家。