我在日常生活中写了相当数量的linq,但大多是简单的陈述。我注意到在使用where子句时,有很多方法可以编写它们,并且每个方法都有相同的结果。例如;
from x in Collection
where x.Age == 10
where x.Name == "Fido"
where x.Fat == true
select x;
至少就结果而言似乎与此相当:
from x in Collection
where x.Age == 10 &&
x.Name == "Fido" &&
x.Fat == true
select x;
除了语法之外还有其他区别吗?如果是这样,首选的风格是什么?为什么?
答案 0 :(得分:130)
编辑:LINQ to Objects没有表现出我的预期。您可能对我刚刚撰写的blog post感兴趣...
它们在所谓的内容方面有所不同 - 第一个相当于:
Collection.Where(x => x.Age == 10)
.Where(x => x.Name == "Fido")
.Where(x => x.Fat == true)
后者相当于:
Collection.Where(x => x.Age == 10 &&
x.Name == "Fido" &&
x.Fat == true)
现在实际的区别取决于被调用的Where
的实现。如果它是一个基于SQL的提供程序,我希望这两个最终创建相同的SQL。如果它在LINQ to Objects中,则第二个将具有较少的间接级别(仅涉及两个迭代器而不是四个)。这些间接级别在速度方面是否重要是另一回事。
通常我会使用几个where
子句,如果他们觉得他们代表了明显不同的条件(例如,一个与一个对象的一部分有关,一个是完全独立的)和一个where
当各种条件密切相关时(例如,特定值大于最小值且小于最大值)。基本上,在任何轻微的性能差异之前,值得考虑可读性。
答案 1 :(得分:71)
第二个会更高效,因为它只有一个谓词来评估集合中的每个项目,就像在第一个项目中一样,它首先将第一个谓词应用于所有项目和结果(在此处缩小) point)用于第二个谓词,依此类推。每次通过结果都会缩小,但仍然需要多次通过。
此外,链接(第一种方法)仅在您对谓词进行AND运算时才有效。像x.Age == 10 || x.Fat == true
这样的东西不能用于你的第一种方法。
答案 2 :(得分:12)
第一个将实施:
Collection.Where(x => x.Age == 10)
.Where(x => x.Name == "Fido") // applied to the result of the previous
.Where(x => x.Fat == true) // applied to the result of the previous
相比更简单(并且更快可能更快):
// all in one fell swoop
Collection.Where(x => x.Age == 10 && x.Name == "Fido" && x.Fat == true)
答案 3 :(得分:11)
我跑的时候
from c in Customers
where c.CustomerID == 1
where c.CustomerID == 2
where c.CustomerID == 3
select c
和
from c in Customers
where c.CustomerID == 1 &&
c.CustomerID == 2 &&
c.CustomerID == 3
select c customer table in linqpad
针对我的Customer表,它输出相同的sql查询
-- Region Parameters
DECLARE @p0 Int = 1
DECLARE @p1 Int = 2
DECLARE @p2 Int = 3
-- EndRegion
SELECT [t0].[CustomerID], [t0].[CustomerName]
FROM [Customers] AS [t0]
WHERE ([t0].[CustomerID] = @p0) AND ([t0].[CustomerID] = @p1) AND ([t0].[CustomerID] = @p2)
所以在转换为sql时没有区别,你已经在其他答案中看到它们将如何转换为lambda表达式
答案 4 :(得分:3)
在幕后,两个语句将转换为不同的查询表示。 <{1}} QueryProvider
取决于Collection
,可能会优化或不优化。
当这是一个linq-to-object调用时,多个where子句将导致一组IEnumerables相互读取。使用单子句形式将有助于此处的表现。
当底层提供程序将其转换为SQL语句时,两个变体创建相同语句的可能性都很大。