关于延期执行的疑问

时间:2012-07-20 11:01:38

标签: linq deferred-execution

假设我有这个:

IEnumerable<MyObject> StructsTemp;

我在StructsTemp上写了n个查询,以便从DB填充,依此类推。 稍后,我执行它们调用.ToList()

IList<MyObject> StructsFinal = StructsTemp.ToList();
... some queries on StructsFinal ....
StructsTemp = StructsFinal;

如果以后我这样做怎么办?

StructsTemp.Count()

它会在StructsTemp上重新执行n次查询吗?这会重新执行StructsTemp.ToList()吗?这会重新执行StructsFinal上的所有查询吗?

2 个答案:

答案 0 :(得分:1)

如果您将List<T>的引用分配给变量StructsTemp,则IEnumerable<T> actually List<T>并将使用{{1} }而不是枚举基础序列。

Count

因此后者将始终返回相同的值,因为它在新集合中持久存在。当底层集合发生变化时,前者可以在每次迭代时返回不同的结果(f.e。var numbers = new []{ 1,2,3 }; IEnumerable<int>evenNumbers = numbers.Where(i=> i % 2 == 0); // deferred, will enumerate the sequence to count the even numbers int count = evenNumbers.Count(); evenNumbers = evenNumbers.ToList(); // not deferred, using the Count property of List<T> count = evenNumbers.Count(); 导致numbers.Remove(2)为0)。

修改

以下是该行为的更有意义的演示:http://ideone.com/91Yrh

答案 1 :(得分:0)

ToList()将强制评估StructsTemp,无论是什么,但它对随后的Linq没有影响。

... some queries on StructsFinal ....可能会或可能不会进行延迟评估,让我们假设它们是。

Count()扩展名不是懒惰的,因此会强制执行... some queries on StructsFinal ....

顺便说一句,如果... some queries on StructsFinal ....的结果实现了ICollection<T>,就像IList<T>那样,那么Count()扩展名只会访问Count的{​​{1}}属性结果。