是否延迟执行
本文关键字:执行 延迟 是否 | 更新日期: 2023-09-27 18:04:10
下面关于延迟执行的评论是否正确?
1. var x = dc.myTables.Select(r=>r);//yes
2. var x = dc.myTables.Where(..).Select(r=>new {..});//yes
3. var x = dc.myTables.Where(..).Select(r=>new MyCustomClass {..});//no
换句话说,我一直认为投射自定义类对象总是会导致紧急执行。但我找不到支持或否认它的参考文献(尽管我看到的结果与之矛盾,因此这篇文章)
问题中的每个语句都是延迟执行的例子。Select
和Where
语句的内容对结果值是否延迟执行没有影响。Select
+ Where
表述本身说明了这一点。
作为反例考虑Sum
方法。不管输入是什么,它总是急切地执行。
var sum = dc.myTables.Sum(...); // Always eager
为了证明您的观点,您的测试应该是这样的:
var tracer = string.Empty;
Func<inType, outType> map = r => {
tracer = "set";
return new outType(...);
}
var x = dc.myTables.Where(..).Select(map);
// this confirms x was never enumerated as tracer would be "set".
Assert.AreEqual(string.Empty, tracer);
// confirm that it would have enumerated if it could
CollectionAssert.IsNotEmpty(x);
根据我的观察,强制立即执行的唯一方法是强制对集合进行迭代。我通过在LINQ上调用.ToArray()
来做到这一点。
通常返回序列的方法使用延迟执行:
IEnumerable<X> ---> Select ---> IEnumerable<Y>
和返回单个对象的方法不会:
IEnumerable<X> ---> First ---> Y
所以,像Where
, Select
, Take
, Skip
, GroupBy
和OrderBy
这样的方法使用延迟执行是因为它们可以,而像First
, Single
, ToList
和ToArray
这样的方法不使用延迟执行是因为它们不能。
.Select(...)
总是被延迟。
当你使用IQueryable<T>
时,这个和其他延迟执行方法建立一个表达式树,直到它被迭代才编译成一个实际的可执行表达式。也就是说,您需要:
- 对预计的可枚举对象执行for-each。
- 调用一个在内部枚举可枚举的方法(即:
.Any(...)
,.Count(...)
,.ToList(...)
,…).