我喜欢匿名的lambdas;它们让您简明扼要地表达列表中的复杂选择。 LINQ做了类似的事情,所以我想我会尝试一下(最后)。
作为经常使用lambdas选择集合子集的人,何时应该使用LINQ?何时应该使用lambdas?有this one之类的问题显示10-100倍的差异以某种方式表现。
答案 0 :(得分:5)
延迟LINQ评估。 primes
和numbers.Where(n => isOddAndNotDivisibleBy(n))
的表达式与编译器相同。在这两种情况下,只有在评估表达式的结果时才会调用isOddAndNotDivisibleBy
。在这种情况下,ToArray
和c
之间的b
会强制进行评估。如果您在a
和b
之间添加了ToArray,那么您会得到类似的时间。
您可以尝试进行比较:
var primes = (
from n in numbers
where isOddAndNotDivisibleBy(n)
select n).ToArray();
答案 1 :(得分:3)
你称之为“LINQ”,实际上称为LINQ查询语法。而你所谓的“匿名lambda”实际上称为LINQ方法语法。重要的是表达式:
from n in numbers
where isOddAndNotDivisibleBy(n)
select n
实际上在编译之前转换为:
numbers.Where(n => isOddAndNotDivisibleBy(n))
这意味着如果您直接使用前者或后者,您将获得相同的IL代码。
所以区别在于其他地方。这是ToArray()
电话。 Where()
很懒惰。这意味着它几乎没有任何作用,除非您实际以某种方式迭代结果序列。这意味着只需调用Where()
即可。但是如果你调用ToArray()
,实际上会迭代该集合并立即计算结果。这就是为什么你会看到如此巨大的差异。
修改强>
修改后的问题:为什么使用一种语法而不是另一种?主要选择更具可读性的那个。
您无法使用查询语法(First()
,Aggregate()
,Concat()
Zip()
,引入索引的重载,...)来表达一些方法和重载。但是,您可以对查询的一部分使用一种语法,对其余部分使用另一种语法。
查询语法还有一个强大的功能,无法使用方法语法轻松表达:透明标识符,例如使用let
子句时。
但两种语法之间没有性能差异,至少在正确使用时是这样。
答案 2 :(得分:1)
您的测试不一样:您在ToArray()
和b
之间调用c
,它将在实际执行查询后分配(然后重新分配,然后重新分配)内存
在a
和b
之间,您只需创建一个查询,在执行时将执行计算。调用ToList()
,ToArray()
或通过foreach
循环迭代查询实际上会强制执行它;它应该花费相同的时间,因为它将从查询理解语法转换为一系列与第二次测试匹配的扩展方法调用。
最后,永远不要使用DateTime.Now
作为时间;使用StopWatch
。
答案 3 :(得分:1)
因为您没有执行linq,只需执行primes .ToArray()
然后比较它们。实际上这是linq的deffered execution行为,它只是创建查询并且没有运行它,直到你用foreach
,ToList
,...等函数执行它。 / p>
你所做的一切都是linq,因为两者都在Enumerable类的IEnumerable上使用了一些扩展方法,只是第一个是查询语法,第二个是Dot Notation语法。在msdn linq中看到它们。
答案 4 :(得分:0)
这两种情况确实是相同的LINQ 查询 ,但语法糖含量不同。
查询是什么意思? LINQ查询,无论您使用mySequence.Where(i => i > 5)
还是(from item in mySequence where item > 5)
创建它,唯一存储的数据都是允许您枚举序列的数据。
当您ToArray
或ToList
或ToDictionary
或foreach
时,会对序列进行评估,这就是为什么您有如此巨大的性能差距 - 即您的第一次查询未评估。永远。