多参数linq表达式如何初始化其参数?

时间:2010-11-18 14:51:22

标签: c# linq lambda

在此post中,问题的解决方案是:

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

多参数(即(item, index))的概念对我来说有点令人费解,我不知道缩小谷歌搜索结果的正确用语。所以1)那叫什么?更重要的是,2)非可枚举变量如何初始化?在这种情况下,index如何编译为int并初始化为0?

感谢。

3 个答案:

答案 0 :(得分:13)

Lambda表达式有各种语法选项:

() => ... // 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 (并返回{ {1}}匹配)。因此,提供索引的是bool实现 - 类似于:

Where

答案 1 :(得分:4)

使用LINQ时,请记住您正在将方法委托传递给Where方法。您正在调用的Where的特定重载采用带有签名Func<T,int,bool>的方法,并将为list中的每个项调用此方法。在内部,这个特殊的方法是为每个迭代的项保持计数,并使用该值作为第二个参数调用提供的委托:

var result=suppliedDelegate(item,count)

答案 2 :(得分:2)

这个答案更具技术性......请记住,lambdas只是匿名委托的合成快捷方式(匿名方法)。 编辑:根据Where的签名,它们也可以是表达式树(请参阅Marc的评论)。

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++;
    }
}

这就是索引初始化并传递给你的委托(匿名,lambda或其他)的地方。