假设我们得到了这样的代码:
IEnumerable<Foo> A = meh();
IEnumerable<Foo> B = meh();
var x =
from a in A
from b in B
select new {a, b};
我们还假设meh
返回IEnumerable
,在迭代时会执行大量昂贵的计算。当然,我们可以通过
IEnumerable<Foo> A = meh().ToList();
我的问题是,如果需要手动缓存A和B,或者上述查询在执行期间缓存A和B本身的结果,那么每行只计算一次。 2 * n和n * n计算的差异可能很大,我没有找到MSDN中行为的描述,这就是我要问的原因。
答案 0 :(得分:4)
假设你的意思是LINQ to Objects,它肯定不会做任何缓存 - 也不应该,IMO。如果您明白我的意思,那么您正在构建查询,而不是查询结果。除了其他任何东西之外,您可能希望迭代一个大于可以合理地保存在内存中的序列(例如,迭代多千兆字节日志文件中的每一行)。我当然不希望LINQ尝试为我缓存它!
如果您希望对查询进行评估和缓冲以便以后快速访问,则调用ToList()
可能是您最好的方法。
请注意,对于A来说,对于依赖,B完全有效,这是不缓存的另一个原因。例如:
var query = from file in Directory.GetFiles("*.log")
from line in new LineReader(file)
...;
您真的不希望LINQ缓存读取第一个日志文件的结果,并对每个日志文件使用相同的结果。我想编译器可能会注意到第二个from
子句不依赖于第一个{{1}}子句中的范围变量 - 但它仍然可能依赖于某些副作用或其他副作用。