LINQ to SQL PredicateBuilder

▼魔方 西西 提交于 2019-12-04 19:31:08


Im using the PredicateBuilder as seen here, everything works great, and now i can genrate Dynamic LINQ to SQL expressions, but the thing that i dont understand is why when i am on a loop like this:

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);

Why must i use that temp variable?, i try to use the "f" iterator variable but it only get the last value on the list for each iteration, like it is passed by reference...


Because PredicateBuilder is building up an expression which will be executed at a later point in time. When the compiler is generating the closure for the delegate, it finds any values which are created in the current scope, and carries them into the closure as well. Since InstrumentID is a value type (int), initializing and copying the value means each delegate/closure will carry that value with it. If you don't create a copy of the value each time, the expression will simply have a literal reference to f.InstrumentID, not to its underlying value. So later on, when the expression is actually executed, f.InstrumentID is evaluated and it will come out as whatever it was last set to, which is the last iteration.


Because it's not evaluating the condition, but simply building the expression. The expression binds to the variable defined in the foreach, which retains it's reference throughout the execution of the entire loop. Redefining it with a temporary variable forces each expression to use a different variable, which forces it to refer to the instance with the value at each iteration rather than having all iterations refer to the single reference and having the value of just the last iteration.