尝试使用c#了解LINQ代码

时间:2012-07-10 16:08:35

标签: c# linq

我不确定这是否是正确的问题,如果没有,我很抱歉。

使用与以下相同的代码:

C# LINQ expression question

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);
}
// Output:
// five
// six
// seven
// eight
// nine

系统如何知道,digit是数字中的项目,index是数组中的位置?

4 个答案:

答案 0 :(得分:6)

Where扩展方法的特定重载被定义为接受Func,其中第一个参数是元素,第二个参数是该元素的索引。这在documentation

中明确提到
  

谓词

     

输入:System.Func<TSource, Int32, Boolean>

     

一个功能   测试每个源元素的条件; 的第二个参数   function表示源元素的索引

强调我的。

答案 1 :(得分:2)

这只是一个命名的事情,你可以命名数字,并索引任何东西。这只是一个匿名函数的lambda表达式......它可以被重写:

(string digit, int index) => digit.Length < index

因此,名称与您通常在方法中设置的任何参数相同。 C#引擎识别名称没有什么特别之处。

(string index, int digit) => index.Length < digit

以上也会起作用......这会令人困惑,但它会起作用。只是为了表明名称可以是你想要的任何东西

如果您要提及如何签名本身那么这是由于overload of the Where function

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

因此,在这种情况下,TSource为string,使得Func变为Func<string, int, bool>。这意味着lambda必须采用string参数后跟int参数,并返回bool

答案 2 :(得分:1)

您正在使用的Where的重载是这样实现的:

public static IEnumerable<T> Where<T>(
      this IEnumerable<T> list, Func<T,int,bool> predicate)
{
   int num = -1;
   foreach (T current in list)
   {
      num++;
      if (predicate(current, num))
      {
         yield return current;
      }
   }
   yield break;
}

如您所见,在每次迭代中,调用谓词(即传递的lambda表达式),传递列表的当前元素和当前索引。

通过这种方式,lambda表达式中的代码知道元素及其索引。

答案 3 :(得分:0)

因为where的重载作为谓词使用了这样的函数:

Func<TSource, int, bool>

这个谓词ios的语义被定义,所以第二个参数是索引。因此,如果你传递一个带有两个args的lambda,那就是调用where的版本。