Как многопараметрическое выражение linq инициализирует их параметр? - PullRequest
11 голосов
/ 18 ноября 2010

В этом сообщении решение проблемы:

list.Where((item, index) => index < list.Count - 1 && list[index + 1] == item)

Концепция многопараметрии (то есть (item, index)) немного озадачивает меня, и я не знаю правильного слова, чтобы сузить результаты поиска в Google. Итак 1) Как это называется? И что более важно, 2) Как инициализируется не перечисляемая переменная? В этом случае как index компилируется как int и инициализируется в 0?

Спасибо.

Ответы [ 3 ]

13 голосов
/ 18 ноября 2010

Лямбда-выражения имеют различные синтаксические параметры:

() => ... // no parameters
x => ... // single parameter named x, compiler infers type
(x) => ... // single parameter named x, compiler infers type
(int x) => ... // single parameter named x, explicit type
(x, y) => ... // two parameters, x and y; compiler infers types
(int x, string y) => ... // two parameters, x and y; explicit types

Тонкость здесь в том, что Where имеет перегрузку, которая принимает Func<T, int, bool>, представляющую значение и index соответственно (и возвращающее bool для совпадения) , Так что именно реализация Where обеспечивает индекс - что-то вроде:

static class Example
{
    public static IEnumerable<T> Where<T>(this IEnumerable<T> source,
        Func<T, int, bool> predicate)
    {
        int index = 0;
        foreach (var item in source)
        {
            if (predicate(item, index++)) yield return item;
        }
    }
}
4 голосов
/ 18 ноября 2010

При использовании LINQ помните, что вы передаете делегат метода методу Where. Конкретная перегрузка Where, которую вы вызываете, принимает метод с подписью Func<T,int,bool> и вызывает этот метод для каждого элемента в list. Внутренне этот конкретный метод ведет подсчет для каждого итерированного элемента и вызывает предоставленный делегат, используя это значение в качестве второго параметра:

var result=suppliedDelegate(item,count)
2 голосов
/ 18 ноября 2010

Этот ответ немного более технический ... Помните, что лямбды - это просто синтетические ярлыки для анонимных делегатов (которые являются анонимными методами). Редактировать: Они также могут быть деревьями выражений в зависимости от подписи Where (см. Комментарий Марка).

list.Where((item, index) => index < list.Count - 1 && list[index + 1] == item)

функционально эквивалентно

// inline, no lambdas
list.Where(delegate(item, index) { return index < list.Count - 1 && list[index + 1] == item; });

// if we assign the lambda (delegate) to a local variable:
var lambdaDelegate = (item, index) => index < list.Count - 1 && list[index + 1] == item;

list.Where(lambdaDelegate);

// without using lambdas as a shortcut:
var anonymousDelegate = delegate(item, index)
    {
        return index < list.Count - 1 && list[index + 1] == item;
    }

list.Where(anonymousDelegate);

// and if we don't use anonymous methods (which is what lambdas represent):
function bool MyDelegate<TSource>(TSource item, int index)
{
    return index < list.Count - 1 && list[index + 1] == item;
}

list.Where(MyDelegate);

Метод Where имеет следующую подпись:

public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, int, bool> predicate);

, что эквивалентно:

delegate bool WhereDelegate<TSource>(TSource source, int index);
public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, WhereDelegate<TSource> predicate);

Здесь определены элемент и индекс.

ПозадиWhere может сделать что-то вроде (просто предположение, вы можете декомпилировать, чтобы увидеть):

public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
{
    int index = 0;

    foreach (TSource item in source)
    {
        if (predicate(index, source))
             yield return item;

        index++;
    }
}

Так вот, где индекс инициализируется и передается вашему делегату (анонимному, лямбда или как-то иначе).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...