我没有理解以下查询与应使用哪种查询的条件之间的区别:
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 };
答案 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
版本。