gpt4 book ai didi

c# - 使用查询表达式时缓存?

转载 作者:太空宇宙 更新时间:2023-11-03 22:26:48 24 4
gpt4 key购买 nike

我正在阅读一篇关于查询表达式如何延迟执行的文章。这是否意味着当我们有一个像这样的集合时:

IEnumerable<int> collection = from i in integers where i % 2 == 0 select i;

每次 collection 都会重新计算被访问了?

如果是这样,处理这个问题的一般做法是什么?要转换成新的集合?

另外,为什么 C# 设计者选择这种方式,而不是在第一次访问集合后将结果缓存到集合中?

还有运行时如何知道 collection以这种方式表现(延迟执行),不像另一个 IEnumerable<T>我可能会使用 List<T> 创建哪个不会推迟处决?


编辑:

像这样的情况呢:

List<int> ints = new List<int> ( ) { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };

var even = from i in ints where i % 2 == 0 select i;

ints.AddRange ( new List<int> ( ) { 10, 20, 30, 40, 50 } );

foreach ( int i in even )
{
Console.WriteLine ( i );
}

输出:

2, 4, 6, 8, 0, 10, 20, 30, 40, 50

通过缓存,行为是否更符合预期?

最佳答案

是的,每次都会重新计算。

如果你想缓存它,在结果上使用 ToArray()(如果你想稍后添加新项目,则使用 ToList())。

它在第一次尝试后不缓存它的原因是因为以线程安全的方式正确地完成它是相当棘手的。通常,枚举集合被认为是线程安全的操作。但是,如果实现在枚举项目时缓存项目,那么它要么对多个读取器变得不安全(令用户感到惊讶并且非常不受欢迎),要么在每一步都对缓存进行显式锁定,这会显着影响性能。即使您实际上没有多个线程同时读取集合,这种性能损失也会存在 - 锁本质上是昂贵的。

另一点是,当查询表达式引用在执行点和枚举结果点之间发生变化的可变变量时,缓存行为不是很明显。当您进行急切评估时,这些值就是它们在查询点的值。当您执行非缓存延迟评估时,值始终是它们在枚举点的值。有了缓存,你不知道——这取决于你是否第一次枚举它。

还有一点是它无法真正知道是否需要缓存。如果您只打算枚举序列一次(这是一种非常常见的情况),那么缓存项目既浪费时间又浪费内存。

F# 实际上有一个用于这种惰性缓存序列的标准类型,称为 LazyList - 您可以将任何 IEnumerable 包装到其中以获得所需的语义,所有上述注意事项。

关于c# - 使用查询表达式时缓存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1101126/

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