3 回答

TA贡献1820条经验 获得超3个赞
为 DoStuff() 的每次调用执行还是以某种方式保存在内存中?
它本身并不保存在内存中,因此以下有时是值得优化的:
IEnumerable<int> even = items.Where(x => x % 2 == 0);
even = even.ToList(); // now it is held in memory
DoStuff1(even);
DoStuff2(even);
DoStuff3(even);
是否需要 ToList() 取决于 DoStuff() 的作用、源列表与过滤列表的大小、枚举的成本等。
请注意,当items时间稍长并且所有 DoStuff 方法都有一个主循环foreach(var item in items.Take(3))时,主方法中的 ToList() 将是一个昂贵的去优化。

TA贡献1808条经验 获得超4个赞
澄清:
在您的行中:
IEnumerable<int> even = items.Where(x => x % 2 == 0);
不计算表达式,因此实际上不会发生迭代。这就是所谓的“延迟评估”。注意:这在概念上独立于接口实现,因此无论它是 List<> 或 [] 等(当然可以针对此主要概念进行实现,但这超出了问题的范围)
当您开始迭代时开始执行even
,例如使用foreach
or GetEnumerator()
then Next()
or FirstOrDefault
or ToList() 或 ToArray() 等。
虽然我们没有看到您的DoStuffX()
代码,但您可能会做类似的事情。
回答
您所问的主要与上述延迟评估无关:它与缓存有关。如果不缓存结果,迭代会发生多次。评估(迭代)和缓存的最简单模式是执行 ToList()
var cached = even.ToList();
(请注意,并非所有 IEnumerable 实现都允许多次迭代,但 List<> 允许。

TA贡献1829条经验 获得超7个赞
他怎么能把它保存在记忆中?不可能。必须执行。
延迟并不意味着缓存。这意味着该行
IEnumerable even = items.Where(x => x % 2 == 0);
可能不执行任何操作。不是开玩笑——它可能会被推迟。
然后在行中
DoStuff1(偶数);
它可以执行。
当 items 不是内存列表而是数据库时,可能是 cmplex 的查询,人们会说“哦,我的 foreach 在它到达第一行之前花了 1 分钟”——这就是延迟的意思。在这种情况下,它只会发送 SQL 并在请求第一项时执行它。
- 3 回答
- 0 关注
- 215 浏览
添加回答
举报