8

我正在阅读“LINQ Pocket Reference”一书,有一个特定的示例(下面稍作修改)我很难理解......书中的解释有点简短,所以我想知道是否有人可以为我一步一步地分解它,这样它才有意义......

    IEnumerable<char> query2 = "Not what you might expect";
    foreach (char vowel in "aeiou")
    {
        var t = vowel;
        query2 = query2.Where(c => c != t);
        // iterate through query and output (snipped for brevity)
    }

输出这个:

    不是你所期望的
    不是你可能的 xpct
    不是你想的 xpct
    Nt wht yu mght xpct
    Nt wht y mght xpct

这对我来说很有意义......但是,这不是。

    IEnumerable<char> query2 = "Not what you might expect";
    foreach (char vowel in "aeiou")
    {
        query2 = query2.Where(c => c != vowel);
        // iterate through query and output (snipped for brevity)
    }
    不是你所期望的
    不是你可能的 xpct
    不是你所期望的
    Nt你可能期望什么
    不是你所期望的

这不...

有人可以更好地解释这里到底发生了什么吗?

4

2 回答 2

10

第一个示例发生的情况是 vowel 的值被捕获到本地(在 for 循环的范围内)变量中。

然后,查询的 where 子句将使用该捕获的变量。像这样的 where 子句使用匿名方法/lambda 方法,它可以捕获局部变量。然后发生的是它捕获变量的当前值。

然而,在第二个类中,它不捕获当前值,只捕获要使用的变量,因此由于这个变量发生了变化,每次执行循环时,都会在最后一个之上构建一个新的 Where 子句,但是由于您更改了变量,因此您还需要修改所有前面的内容。

所以在第一个例子中,你得到了这种类型的查询:

IEnumerable<char> query2 = "Not what you might expect";
Char t1 = 'a'; query2 = query2.Where(c => c != t1);
Char t2 = 'e'; query2 = query2.Where(c => c != t2);
Char t3 = 'i'; query2 = query2.Where(c => c != t3);
Char t4 = 'o'; query2 = query2.Where(c => c != t4);
Char t5 = 'u'; query2 = query2.Where(c => c != t5);

在第二个例子中,你得到这个:

IEnumerable<char> query2 = "Not what you might expect";
Char vowel = 'a'; query2 = query2.Where(c => c != vowel);
vowel = 'e'; query2 = query2.Where(c => c != vowel);
vowel = 'i'; query2 = query2.Where(c => c != vowel);
vowel = 'o'; query2 = query2.Where(c => c != vowel);
vowel = 'u'; query2 = query2.Where(c => c != vowel);

当您执行第二个示例时, 的值vowel将是 'u',因此只有 u 将被删除。但是,您有 5 次循环在同一字符串上删除“u”,但当然只有第一个会这样做。

这种对变量的捕获是我们在使用匿名方法/lambda 时都会遇到的事情之一,您可以在此处阅读更多相关信息:C# In Depth: The Beauty of Closures

如果您向下浏览该页面到Comparing capture strategy: complex vs power下的文本,您会发现这种行为的一些示例。

于 2008-12-23T19:08:38.910 回答
1

其实,重读一遍,是有道理的。使用 temp 变量意味着在查询中捕获 temp 本身......我们正在评估循环五次,因此每个查询版本都有五个实例化的 temp 变量引用。

在没有 temp 变量的情况下,只有对循环变量的引用。

所以五个参考对一个参考。这就是为什么它会产生如图所示的结果。

在第一种情况下,一旦完全评估了循环,查询就使用了对临时变量的五个引用,因此分别删除了 a、e、i、o 和 u。

在第二种情况下,它做同样的事情......只有所有五个引用都指向同一个变量,显然只包含一个值。

故事的寓意:思考“参考”而不是“价值”。

那么,这对现在其他人有意义吗?

于 2008-12-23T19:09:04.307 回答