如何在LINQ Where()中使用额外的int参数

本文关键字:参数 int LINQ Where | 更新日期: 2023-09-27 18:29:39

请注意,这不是一个关于委托一般是什么的问题。此外,我看过医生,却没有任何智慧。

在LINQ中,我可以使用这样的东西。

using(Model model = new Model())
{
   return model.Things
               .Where(thing => thing.IsGood);
}

我可以看到返回类型(运算符的左对象)是类型Thing,条件(运算符的右对象)是bool。Intellisense告诉我可以从这两个中挑选,我被第二个弄糊涂了。

Func<Thing, bool>  
Func<Thing, int, bool>

我假设lambda运算符只是实际调用的语法糖。这是正确的吗?如果是,那个整数在做什么?我该如何指定它?

如何在LINQ Where()中使用额外的int参数

来自此重载的文档:

谓词

类型:System.Func<TSource, Int32, Boolean>

用于测试每个源元素的条件的函数;函数的第二个参数表示源元素的索引。

正如这所表明的,整数是元素的索引。

所以,

var everyTwo = input.Where((c, i) => i % 2 == 0);

例如,仅每隔一秒返回一个元素。上面链接的文档有一个稍微复杂一点的用例示例,它涉及两个参数。

我不确定这是否只是一个拼写错误,但您链接到的文档似乎是针对不包含此参数的重载的,这可能解释了为什么您找不到对此的解释。

正如评论中已经提到的,文档指出第二个重载:-

基于谓词筛选值序列。每个元素的索引用于谓词函数的逻辑。

这是参考代码,我想它会让你明白:-

public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, 
                                                   Func<TSource, int, bool> predicate) 
{
    if (source == null) throw Error.ArgumentNull("source");
    if (predicate == null) throw Error.ArgumentNull("predicate");
    return WhereIterator<TSource>(source, predicate);
}
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)) yield return element;
   }
}

您可以看到我们提供的索引是如何在foreach语句中使用的。因此,我们可以将谓词用作:-

.Where((thing, index) => thing.SomeIntProperty <= index * 2);

用一个例子来说明,而不是简单地引用MSDN帮助页面:

取此代码:

var list = new List<string> { "a", "b", "c" }
var index = 0;
foreach (var item in list)
{
    if (item == "b" && index == 1) {
        Console.WriteLine(item);
    }
    index++;
}

成为

var list = new List<string> { "a", "b", "c" }
var items = list.Where((item, index) => item == "b" && index == 1)
foreach (var item in items) {
    Console.WriteLine(item);
}

(您可以对写行等使用其他linq命令,这是为了说明Where

正如MSDN中所说:

基于谓词筛选值序列。每个元素的索引用于谓词函数的逻辑。

你什么时候需要这个?例如,您可能需要所有具有偶数索引的元素:

return model.Things
    .Where((thing, index) => index % 2 == 0);

此外,在未来,您可以使用这个为我们提供.net源代码的网站来更多地发现和学习这些东西。例如,这里是Where()方法的重叠的实现:

 public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, int, bool> predicate) {
            if (source == null) throw Error.ArgumentNull("source");
            if (predicate == null) throw Error.ArgumentNull("predicate");
            return WhereIterator<TSource>(source, predicate);
        }

我们可以看到它返回WhereIterator方法:

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)) yield return element;
            }
        }

我们可以看到,实际上Linq使用了foreach循环,并通过将index变量增加一来获得当前元素的索引。

Where上有两篇MSDN文章。你链接到的那个和这个。

用法语法如下。

using(Model model = new Model())
{
  return model.Things
    .Where((thing, counter) => thing.IsGood < counter);
}

正如您所看到的,它在这个特殊情况下没有什么意义,我从来没有需要使用它。然而,如果需要,它就在那里。您可以在提供的链接中找到一个示例。