2009-10-27 30 views
9

Ich benutze den PredicateBuilder wie hier gesehen http://www.albahari.com/nutshell/predicatebuilder.aspx, alles funktioniert gut, und jetzt kann ich dynamische LINQ zu SQL-Ausdrücke generieren, aber die Sache, die ich nicht verstehe, ist warum, wenn ich auf einer Schleife wie folgt bin: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); 
     } 

Warum muß ich diese temporäre Variable verwenden ?, ich versuche, den „f“ Iteratorvariable zu verwenden, aber es nur den letzten Wert auf der Liste für jede Iteration erhalten, wie es durch Referenz übergeben wird ...

Antwort

10

Da PredicateBuilder einen Ausdruck erstellt, der zu einem späteren Zeitpunkt ausgeführt wird. Wenn der Compiler den Abschluss für den Delegaten generiert, findet er alle Werte, die im aktuellen Bereich erstellt werden, und trägt sie auch in den Abschluss. Da InstrumentID ein Werttyp (int) ist, bedeutet das Initialisieren und Kopieren des Werts, dass jeder Delegat/Closure diesen Wert mit sich führt. Wenn Sie nicht jedes Mal eine Kopie des Werts erstellen, hat der Ausdruck einfach einen literalen Verweis auf f.InstrumentID, nicht auf den zugrunde liegenden Wert. Später, wenn der Ausdruck tatsächlich ausgeführt wird, wird f.InstrumentID ausgewertet und es wird ausgegeben, was auch immer als letztes gesetzt wurde, was die letzte Iteration ist.

+0

das scheint ziemlich interessant, wo bekomme ich Dokumentation für dieses Thema – JOBG

2

Weil es nicht die Bedingung auswertet, sondern einfach den Ausdruck erstellt. Der Ausdruck bindet an die im foreach definierte Variable, die während der Ausführung der gesamten Schleife ihre Referenz beibehält. Wenn Sie ihn mit einer temporären Variablen neu definieren, wird jeder Ausdruck gezwungen, eine andere Variable zu verwenden, wodurch er bei jeder Iteration auf die Instanz mit dem Wert verweist, anstatt alle Iterationen auf die einzelne Referenz zu beziehen und nur die letzte Iteration zu haben.

+0

danke, das ist ein wenig schwierig, es erinnere mich an die Zeit, die ich mit Arrays spielte, und möchte seine Werte nach Wert kopieren .. Kopfschmerzen, vielleicht In einfachen Worten bedeutet dies, dass dies eine faule Last des Wertes ist, der Wert ändert sich über die Zeit und es gibt nur 1 Instante von "f". – JOBG