正确的Linq条款

时间:2011-06-15 15:11:15

标签: c# linq

我在日常生活中写了相当数量的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;

除了语法之外还有其他区别吗?如果是这样,首选的风格是什么?为什么?

5 个答案:

答案 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语句时,两个变体创建相同语句的可能性都很大。