DevCN
菜单
全部文章快讯开发深度热点

C# LINQ:筛选任务并理解延迟执行时机

用 LINQ 筛选任务并求和,通过修改源集合观察延迟查询与 ToArray 快照的区别,明确结果在什么时候计算。


本节目标

用 LINQ 筛选任务并求和,通过修改源集合观察延迟查询与 ToArray 快照的区别,明确结果在什么时候计算。

环境与运行方法

准备 .NET 8 SDK,创建目录后执行 dotnet new console --framework net8.0。用示例替换 Program.cs,执行 dotnet run。这里使用顶层语句,不要再套入另一份 Main。

核心思路

Where 通常返回延迟查询,定义查询不等于已经把结果保存下来。ToArray 会立即枚举并生成数组。本例分别保存查询与快照,再修改源列表,观察两者计数不同。

完整示例

var minutes = new List<int> { 20, -5, 35 };
var query = minutes.Where(value => value >= 0);
var snapshot = query.ToArray();
minutes.Add(10);
Console.WriteLine("query=" + query.Count());
Console.WriteLine("snapshot=" + snapshot.Length);
Console.WriteLine("total=" + query.Sum());

预期输出

query=3
snapshot=2
total=65

逐步理解

创建 query 时并未完成筛选。snapshot 在 Add 前计算,所以保存 20 与 35;后续 Count 枚举 query 时会看到新加入的 10。Sum 又执行一次枚举,得到 65。

如果数据来源昂贵或会变化,重复枚举可能影响性能或结果一致性。需要稳定多次使用时可物化一次,再围绕快照计算;但快照只复制元素值或引用,不保证深层对象不可变。不要把延迟执行误解成自动并行。

常见问题与边界

  • 查询定义处与执行处可能相隔很远。
  • 在枚举期间修改 List 可能触发异常。
  • ToArray 对引用类型元素不等于深拷贝。

动手练习

把 Add(10) 改为 Add(-10),预测三个输出。

参考答案

查询计数仍为 2,快照长度仍为 2,总和为 55。新负值存在于原集合,但被查询条件排除。

DISCUSSION

文章回复

0 条公开回复
未登录回复需要审核后公开
还没有回复,欢迎参与讨论。