LINQ的以下两个查询之间有什么不同

时间:2012-02-04 05:02:02

标签: c# linq

我没有理解以下查询与应使用哪种查询的条件之间的区别:

 var productGroups = 
        from p in products 
        group p by p.Category into g 
        where g.Any(p => p.UnitsInStock == 0) 
        select new { Category = g.Key, Products = g }; 



var productGroups = 
        from p in products 
        group p by p.Category into g 
        where g.Where(p => p.UnitsInStock == 0) 
        select new { Category = g.Key, Products = g }; 

1 个答案:

答案 0 :(得分:4)

区别在于第二个不是合法代码而且不会编译。

where g.Where(...) 

g.Where本身就是一个过滤操作。它产生一个任何类型g的序列。它产生一个布尔值,这是将它用作另一个where表达式中的谓词所需的。

另一方面,g.Any(...)是一个返回布尔值的方法,允许您在查询的where子句中使用它。

第一个查询(合法查询)按类别对您的产品进行分组,然后过滤以选择产品库存为0个单位的组。只要该类别中的任何产品库存中有0个单位,该组就会被选择为包含该类别的匿名类型,然后选择该类别中的产品。

如果你有

var products = new List<Product> 
{
    new Product { Category = "Widgets", Name = "Foo", UnitsInStock = 14 },
    new Product { Category = "Widgets", Name = "Bar", UnitsInStock = 0 },
    new Product { Category = "Frobbers", Name = "Baz", UnitsInStock = 32 },
    new Product { Category = "Frobbers", Name = "Blah", UnitsInStock = 9 }
};

然后Widgets会传递你的谓词,因为它有一个0单位的产品。 Frobbers将被过滤掉。

只需在Any之后应用Where方法,即可修复第二个查询以执行与第一个查询相同的功能。

 where g.Where(p => p.UnitsInStock == 0).Any()

然后,在输出中没有区别,因为谓词是相同的。区别在于指定谓词的位置。在第一个查询中,它使用接受谓词的Any重载,第二个(一旦修复)使用不带谓词但在通过Where方法应用谓词之后的重载。两种方法都通过方法延迟流式传输元素,仅根据需要进行评估以验证条件。因此,主要取决于您使用哪个版本,我只想选择接受谓词的Any版本。