[英]Why must a lambda expression be cast when supplied as a plain Delegate parameter
[英]Why is parameter i preserved across calls to delegate function in lambda expression?
我有以下C#代码,并且发现参数i
的值被传递到lambda表达式委托的下一个调用。
string[] arrayOne = {"One", "Two", "Three", "Three", "Three"};
string[] newArray = arrayOne.Where ((string n, int i)=> {return i++ <=2;} ).ToArray();
// newArray is {"One","Two", "Three"}
我的期望是,新的参数i
会为每次调用该委托传递。 我知道在lambda表达式中使用的局部变量会由于闭包而在所有调用中保留,但这是一个参数。
题:
为什么在所有对委托的调用中都保留参数i
的值?
有两个覆盖linq where
。
public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, int, bool> predicate);
public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate);
您调用use第二个参数int
类型值表示您的数组索引。
public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, int, bool> predicate);
这将返回集合中的索引值小于或等于2的值。
Where ((string n, int i)=> {return i++ <=2;})
但是i++
没有意义,因为您离开了委托函数范围,自动增量i的值不会保留
我的期望是,每次调用代理时都会传递一个新参数。 我知道在lambda表达式中使用的局部变量会由于闭包而在所有调用中保留,但这是一个参数。
两次调用之间不会保留该参数。 但是,第二个参数( int i
)是一个索引 ,因此它由.Where(..)
函数本身中的逻辑递增 。
在Where
,它看起来或多或少是:
public static IEnumerable<T> Where(this IEnumerable<T> data, Funct<T, int, bool> p) {
int i = 0;
foreach(T t in data) {
if(p(t, i)) {
yield return t;
}
i++;
}
}
注意 :如果我们检查源代码,我们会看到它委托给执行逻辑的
WhereIterator
函数。 我听说提供了一个更“干净”的实现方式来解释这个想法。
注意i++
:索引由 Where
函数递增。 无论函数中的i
做什么,我们每次都用另一个值来调用它。 int
不是引用对象,因此您无法更新数字的“状态”。
以以下电话为例:
csharp> arrayOne.Where ((string n, int i)=> {i += 2; return i <= 4;} )
{ "One", "Two", "Three" }
在这里,我们用2
递增i
,并且我们看到确实小于2
索引(或递增2
索引小于4
)仍然相同。 因此,指数不会使两个或三个跳。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.