2016-11-27 3 views
1
string[] digits = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" }; 

var shortDigits = digits.Where((digit, index) => digit.Length < index); 
foreach (var sD in shortDigits) 
{ 
    Console.WriteLine(sD); 
} 

MSDN дает приведенный выше пример кода. Я понимаю, что «цифра» представляет собой одну из строк в массиве. То, что я не понимаю, так это то, как выражение Lambda знает, что второй параметр является индексом строки в массиве.Lambda Выражение понимания проблемы MSDN пример

+1

Что вы имеете в виду 'know'? Второй параметр содержит индекс, потому что это то, что передается ему «Where», так же как первый элемент в исходной последовательности. – Lee

+0

Поскольку это находится в документах https://msdn.microsoft.com/en-us/library/bb549418(v=vs.110).aspx –

ответ

1

выражение лямбды всегда состоит из двух частей:

  • В передней части оператора лямбда => является параметром (ы) ввода. В вашем случае операция .Where дает строку и целое число (digit, index).
  • После того, как лямбда-оператор представляет собой код для возврата bool (путем работы с двумя параметрами). Вы также можете написать это нравится:

В общем, вы можете понять expresison как эта функция:

bool WhereDigits(string digit, int index) 
{ 
    return digit.Length < index; 
} 

Значит, функция возвращает истину для всех цифр с меньшей длины, чем их arrayindex.

0

Ну просто потому, что эта перегрузка реализуется как-то вроде этого (упал общий, чтобы сделать его проще):

static IEnumerable<string> Where(string[] sequence, Func<string, int, bool> predicate) 
{ 
    int index = 0; 
    foreach(var item in sequence) 
    { 
     if (predicate(item, index)) 
      yield return item; 

     index++; 
    } 
} 

Так эта реализация посылает индекс элемента для вашего лямбда-выражения.

Итак, вы называете это так:

string[] digits = { "zero", "one", "two", "three", "four", 
        "five", "six", "seven", "eight", "nine" }; 

var result = Where(digits, PredicateMethod); 

Единственное отличие в том, что я преобразовал лямбда к фактическому методу:

static bool PredicateMethod(string digit, int index) 
{ 
    return digit.Length < index; 
} 
0

Есть два перегруженных метода Where. Один из них принимает Func<string, bool>, а другой принимает Func<string, int, bool>. То, что вы здесь называете, очевидно, последнее.

Делегат Func<string, int, bool> представляет собой метод, который принимает два параметра (int и строку) и возвращает bool. Ваше выражение лямбда имеет два параметра и возвращает bool. Поэтому код компилируется.

Теперь, как метод Where знает индекс?

Это вызывает внутреннюю работу метода Where. Глядя на reference source, Where называет WhereIterator метод, который имеет всю логику индекса в нем:

int index = -1; 
foreach (TSource element in source) { 
    checked { index++; } 
    if (predicate(element, index)) yield return element; 
} 
1

, как это выражение Lambda известно, что второй параметр является индексом строки в массиве

Lambda выражение не знает этого. Where метод расширения знает, потому что он был реализован.

Lambda просто выполняет некоторые параметры, чтобы выполнить свою работу. кто отправляет параметры?Where способ расширения, как вы можете видеть ниже.

static IEnumerable<TSource> WhereIterator<TSource>(IEnumerable<TSource> source, Func<TSource, int, bool> predicate) { 
    int index = -1; 
    foreach (TSource element in source) { 
     checked { index++; } 

     if (predicate(element, index)) // the element and index is being sent to the function. your function executes here. 
      yield return element; 
    } 
} 

Параметры затем приведены здесь, чтобы запустить ваш код

(digit, index) => return digit.Length < index