gpt4 book ai didi

c# - 为什么我的 LINQ 表达式中的这个输出变量没有问题?

转载 作者:行者123 更新时间:2023-11-30 14:29:14 26 4
gpt4 key购买 nike

给定以下代码:

var strings = Enumerable.Range(0, 100).Select(i => i.ToString());
int outValue = 0;
var someEnumerable = strings.Where(s => int.TryParse(s, out outValue))
.Select(s => outValue);
outValue = 3;
//enumerating over someEnumerable here shows ints from 0 to 99

我能够看到每次迭代的 out 参数的“快照”。为什么它可以正常工作,而不是我看到 100 个 3(延迟执行)或 100 个 99(访问修改后的闭包)?

最佳答案

首先,您定义一个查询,strings,它知道如何在查询时生成字符串序列。每次请求一个值时,它都会生成一个新数字并将其转换为字符串。

然后声明一个变量outValue,并为其分配0

然后你定义一个新的查询,someEnumerable,它知道如何在被要求输入一个值时,从查询 strings 中获取下一个值,尝试解析值,如果可以解析该值,则生成 outValue 的值。再一次,我们定义了一个可以执行此操作的查询,但我们没有实际执行此操作的任何

然后将 outValue 设置为 3

然后你向 someEnumerable 询问它的第一个值,你向 Select 的实现询问它的值。要计算该值,它将向Where 询问它的 第一个值。 Where 将询问 strings。 (我们现在将跳过几步。)Where 将得到一个 0。它将调用 0 上的谓词,特别是调用 int.TryParse。这样做的副作用是 outValue 将设置为 0TryParse 返回 true,因此项目被生成。 Select 然后使用其选择器将该值(字符串 0)映射到一个新值。选择器忽略该值并在该时间点生成 outValue 的值,即 0。我们的 foreach 循环现在对 0 做任何事情。

现在我们在循环的下一次迭代中向 someEnumerable 询问它的第二个值。它向 Select 询问一个值,Select 询问 Where,Where 询问 stringsstrings 产生 "1"Where 调用谓词,将 outValue 设置为 1 作为副作用,Select 产生 outValue 的当前值,即 1foreach 循环现在可以对 1 执行任何操作。

所以这里的关键点是由于 WhereSelect 延迟执行的方式,只有在需要值时才立即执行它们的工作,副作用Where 谓词的最终在 Select 中的每个投影之前立即被调用。如果您没有延迟执行,而是在 Select 中的任何投影之前执行所有 TryParse 调用,然后 你会看到每个值 100。我们实际上可以很容易地模拟这个。我们可以将 Where 的结果具体化到一个集合中,然后看到 Select 的结果是 100 一遍又一遍地重复:

var someEnumerable = strings.Where(s => int.TryParse(s, out outValue))
.ToList()//eagerly evaluate the query up to this point
.Select(s => outValue);

综上所述,您的查询并不是特别好的设计。您应该尽可能避免有副作用的查询(例如您的Where)。事实上,查询既会导致副作用,又会观察到它所产生的副作用,这使得遵循所有这一切变得相当困难。更可取的设计是依赖于不会引起副作用的纯功能性方法。在这种情况下,最简单的方法是创建一个尝试解析字符串并返回 int? 的方法:

public static int? TryParse(string rawValue)
{
int output;
if (int.TryParse(rawValue, out output))
return output;
else
return null;
}

这允许我们写:

var someEnumerable = from s in strings
let n = TryParse(s)
where n != null
select n.Value;

此处查询中没有可观察到的副作用,查询也没有观察到任何外部副作用。它使整个查询更容易推理。

关于c# - 为什么我的 LINQ 表达式中的这个输出变量没有问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26662323/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com