即使在Take运算符之前调用Select运算符,也只会为前两个输入元素调用Select表达式:
string[] count = { "one ", "two ", "three ", "four ", "five ", "six " };
IEnumerable<int> results = count.Select(item =>
{
Console.WriteLine(item);
return item.Length;
}).Take(2);
foreach (int i in results);输出:
one two a)假设我们将几个Linq-to-Objects标准查询操作符链在一起,那么调用Take操作符的顺序不重要吗?因此,无论是先调用还是最后调用Take都无关紧要,因为将为其调用lambda表达式的输入元素的数量始终相同?
b)再次假设我们将几个Linq-to-Objects标准查询操作符链接在一起,是否还有其他Linq-to-Objects操作符,它们被调用的顺序不影响lambda表达式被调用的输入元素的数量?
谢谢
发布于 2011-12-07 03:17:43
查询运算符通常只在源集合中向前移动所需数量的步骤,以生成所需数量的输出结果。
在您的示例中,Take()将只需要来自Select()的两个项目,因此这就是Select()将生成的所有内容。Select()的实现可能大致如下(摘自Jon Skeet's blog
private static IEnumerable<TResult> Select<TSource, TResult>(
this IEnumerable<TSource> source,
Func<TSource, TResult> selector)
{
foreach (TSource item in source)
{
yield return selector(item);
}
}排序和分组操作符需要先创建完整的结果集,然后才能返回任何内容(例如OrderBy())。
只要您不使用任何排序、分组、过滤(例如使用Where()或Skip())或任何其他操作符来更改序列中项目的数量,那么您将Take()放在链中的哪个位置并不重要。
发布于 2011-12-07 03:22:27
顺序很重要,但执行通常是延迟的,并且无疑是优化的。如果您的断言/观察是正确的,那么在Take()之前添加ToList()不会影响输出,但它确实会影响输出。ToList()调用在Take()之前强制执行完整枚举,并导致在所有元素上调用Select lambda。
这里的教训是,不要依赖于优化来保证正确性。
string[] count = { "one ", "two ", "three ", "four ", "five ", "six " };
IEnumerable<int> results = count.Select(item =>
{
Console.WriteLine(item);
return item.Length;
})
.ToList()
.Take(2);https://stackoverflow.com/questions/8405399
复制相似问题