我不确定这是否是正确的问题,如果没有,我很抱歉。
使用与以下相同的代码:
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
是数组中的位置?
答案 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的版本。