Я ожидал, что новый параметр мне будет передаваться для каждого вызова делегата. Я знаю, что локальные переменные, используемые в лямбда-выражении, сохраняются во всех вызовах из-за замыканий, но это параметр.
Параметр не сохраняется между вызовами. Второй параметр (int i
), однако, является индексом , и поэтому он увеличивается с помощью логики самой функции .Where(..)
.
В Where
это выглядит примерно так:
public static IEnumerable<T> Where(this IEnumerable<T> data, Funct<T, int, bool> p) {
int i = 0;
foreach(T t in data) {
if(p(t, i)) {
yield return t;
}
<b>i++;</b>
}
}
Примечание : Если мы проверяем исходный код, мы видим, что он делегирует функцию WhereIterator
, которая выполняет логику. Я слышал, предоставил более «чистую» реализацию, чтобы объяснить идею.
Обратите внимание на i++
: индекс увеличивается на функцию Where
. Независимо от того, что делается с i
в функции, мы каждый раз вызываем ее с другим значением. int
не является справочным объектом, поэтому вы не можете обновить"состояние" числа.
Возьмем, к примеру, следующий вызов:
csharp> arrayOne.Where ((string n, int i)=> {i += 2; return i <= 4;} )
{ "One", "Two", "Three" }
Здесь мы увеличиваем i
на 2
, и мы видим, что на самом деле индексы, которые меньше 2
(или индексы, увеличенные на два, меньше 4
), остаются теми же. Таким образом, индекс не делает прыжки из двух или трех.