2009-06-05 33 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