Поскольку PredicateBuilder создает выражение, которое будет выполнено в более поздний момент времени. Когда компилятор создает замыкание для делегата, он находит все значения, созданные в текущей области, и переносит их также в замыкание. Поскольку InstrumentID является типом значения (int), инициализация и копирование значения означает, что каждый делегат / закрытие будет нести это значение вместе с ним. Если вы не создаете копию значения каждый раз, выражение просто будет иметь буквальную ссылку на f.InstrumentID, а не на его базовое значение. Таким образом, позже, когда выражение фактически выполнено, вычисляется f.InstrumentID, и оно будет выглядеть так, как оно было установлено в последний раз, что является последней итерацией.