2009-06-05 37 views
1

以下Lambda和Linq表達式在執行路徑方面是否相同?我猜想我想知道Linq是否會以不同的方式運行,因爲它將在確定枚舉是否有任何內容之前創建IEnumerable,而lambda表達式將停止在它找到的第一個數字上。以下Lambda和Linq表達式是否相同?

var x = valueToMatch 
    .Any(c => Char.IsDigit(c)); 

var y = (from c in valueToMatch 
     select c).Any(c => Char.IsDigit(c)); here 

Thx! Joel

回答

3

它會以不同的方式運行,但沒有任何可觀的方式。如果使用MSIL Disassembler,即使開啓了優化,第一個表達式和第二個表達式的輸出也會略有不同。你也可以使用Reflector來看看它(這有點容易閱讀)。

第二版本將基本上通過像通過每個元件:

[CompilerGenerated] 
private static char <Match2>b__2(char c) 
{ 
    return c; 
} 

它執行的任何(C => Char.IsDigit(c))的表達之前。所以確實有區別。

然而,在我看來,差異非常小。 測試10,000個字符的列表,每個方法的第一個時鐘週期約爲125ms,而第二個方法的時間約爲185ms。

+1

你也可以使用LINQPad來查看IL 。 恕我直言,「從C在valueToMatch選擇C」在這種情況下是相當多餘的 – dplante 2009-06-05 23:05:33

1

它們大致相同。 編譯器可能會優化選擇,兩者將100%完全相同。 無論如何,Linq都是懶惰評估的,所以在這兩種情況下,valueToMatch的枚舉量將完全相同。

+2

編譯器不會優化選擇,並有一個很好的理由。看到我關於這個問題的文章:http://blogs.msdn.com/ericlippert/archive/2008/05/12/trivial-projections-are-usually-optimized-away.aspx – 2009-06-08 16:32:10

0

對於查詢表達式,這代表了identity function

from c in valueToMatch select c 

這意味着表達式的結果將是正好等於輸入,matchToValue。因此,您提供的示例在語義上是等效的。

在非身份選擇的情況下,例如:

from c in valueToMatch select c + ";" 

一個IEnumerable<char>創建其中,列舉時,將消耗的valueToMatch內容和改變它們。

這一呼籲:

(from c in valueToMatch select c + ";").Any(c => Char.IsDigit(c)) 

列舉了內部查詢,直到找到一個匹配。正如你所看到的,不管源查詢如何,在調用Any之前它都不會運行。 IEnumerable<char>實例表示運行查詢的能力,而不是已經運行的查詢。這個概念被稱爲deferred execution