以编程方式构建LINQ查询而没有局部变量欺骗我

假设我的对象处于完美的工作状态(即TDD让我觉得它们有效)。

我有一个我这样创建的列表(正确缩进除外):

var result = from v in vendors from p in v.Products orderby p.Name select p; 

这有效 – 我从所有供应商处获得所有产品。

现在我有一个条件列表,由用户在运行时构建。 让我们应用它们:

 foreach (Attribute a in requiredAttributes) { result = result.Where(p => p.Attributes.Contains(a)); } 

这可能是原始的,但我认为它有用。 但是,在完成此foreach循环后,当您枚举“result”时,它将包含其Attributes属性(也是集合)中具有requiredAttributes集合的LAST属性的所有产品。

对我来说,这种气味就像“a”被覆盖在某处,每次旅行通过循环,只有最后一个适用。

如果没有以某种方式将扩展方法写入IEnumerable,称为ContainsAll(IEnumerable)或类似的东西,我怎么能实现我想要的,这基本上是一个逻辑AND,只给我那些具有所有必需属性的产品?

(为清晰起见编辑。)

问题是foreach循环,以及每次捕获然后更改“a”变量的事实。 通过为循环的每次迭代有效地引入“新”变量并捕获该新变量,这是一个可行的修改。

 foreach (Attribute a in requiredAttributes) { Attribute copy = a; result = result.Where(p => p.Attributes.Contains(copy)); } 

如果你可以使用它,Omer的解决方案是一个更清洁的解决方案,但如果你的真实代码实际上更复杂,这可能会有所帮助:)

编辑:关于这个闭包文章的问题还有更多 – 向下滚动到“比较捕获策略:复杂性与功率”。

 var result = from v in vendors from p in v.Products where requiredAttributes.All(a => p.Attributes.Contains(a)) orderby p.Name select p; 

HTH。

我没有编码,但改变了

 foreach (Attribute a in requiredAttributes){ result = result.Where(p => p.Attributes.Contains(a)); } 

 foreach (Attribute a in requiredAttributes){ Attribute b = a; result = result.Where(p => p.Attributes.Contains(b)); } 

我想也应该修理它。