繁体   English   中英

为什么在lambda表达式中的委托函数调用之间保留参数i?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM