2009-10-27 127 views
9

我在这里看到使用PredicateBuilder http://www.albahari.com/nutshell/predicatebuilder.aspx,一切都很好,现在我可以创建动态LINQ to SQL表达式,但是我不明白的是为什么当我在这样的循环时:LINQ to SQL PredicateBuilder

var inner = PredicateBuilder.False<MyType>(); 
foreach (var f in Filtermodel.InstrumentsFilterList.Where(s => s.isActive)) 
     { 
      int temp = f.InstrumentID; 
      inner = inner.Or(ud => ud.InstrumentId == temp); 
     } 

为什么我必须使用临时变量?我尝试使用了“F”迭代变量,但它只能获得名单上的最后一个值对于每次迭代,就像是按引用传递...

回答

10

由于PredicateBuilder正在构建一个将在稍后时间点执行的表达式。当编译器为委托生成闭包时,它会找到在当前作用域中创建的任何值,并将它们携带到闭包中。由于InstrumentID是一个值类型(int),因此初始化和复制值意味着每个委托/闭包都会随之携带该值。如果您每次都不创建该值的副本,则该表达式将仅具有对f.InstrumentID的文字引用,而不是其基础值。所以稍后,当表达式被实际执行时,f.InstrumentID将被评估,并且它将以最后一次迭代的结果出现。

+0

这似乎很有趣,我在哪里可以得到这个主题的文档 – JOBG 2009-10-27 03:53:10

2

因为它不评估条件,而只是构建表达式。该表达式绑定到foreach中定义的变量,该变量在整个循环的执行过程中保留它的引用。用临时变量重新定义它会强制每个表达式使用一个不同的变量,这会强制它在每次迭代时使用值引用实例,而不是使所有迭代都引用单个引用并使其值仅为最后一次迭代。

+0

谢谢,这有点棘手,它记得我玩数组的时间,并希望通过值复制它的值..头痛,也许简单地说,这意味着这是对数值进行延迟加载,随着时间的推移而变化,并且这仅仅是“f”的1个实例。 – JOBG 2009-10-27 03:58:46