2014-03-14 10 views
4

的问题是:为什么它使用此代码LINQ:为什么数组和列表使用不同的迭代器

if (source is TSource[]) 
    return (IEnumerable<TResult>) new Enumerable.WhereSelectArrayIterator<TSource, TResult>((TSource[]) source, (Func<TSource, bool>) null, selector); 
    if (source is List<TSource>) 
    return (IEnumerable<TResult>) new Enumerable.WhereSelectListIterator<TSource, TResult>((List<TSource>) source, (Func<TSource, bool>) null, selector); 
    else 
    return (IEnumerable<TResult>) new Enumerable.WhereSelectEnumerableIterator<TSource, TResult>(source, (Func<TSource, bool>) null, selector); 
} 

,而不是

if (source is IList<TSource>) 
    return (IEnumerable<TResult>) new Enumerable.WhereSelectIListIterator<TSource, TResult>((List<TSource>) source, (Func<TSource, bool>) null, selector); 
    return (IEnumerable<TResult>) new Enumerable.WhereSelectEnumerableIterator<TSource, TResult>(source, (Func<TSource, bool>) null, selector); 
} 

我的意思是List<T>T[]两个工具IList<T>,他们都具有索引器并实现IEnumerable<T>,因此它们都可以以相同的单数方式迭代,但现在使用不同的迭代器。

+0

从哪里得到这些代码片段? – payo

+0

我会想到,在使用这些迭代器时,LINQ可以做出合理的优化 - 并且可能不会以完全相同的方式迭代它们。但没有挖掘LINQ源,我不能证明这一点,只是一个强烈的预感(ergo,一条评论) – payo

+0

@payo http://referencesource.microsoft.com/#System.Core/System/Linq/Enumerable.cs –

回答

5

它只是一个优化,涵盖了过滤数组或列表的极其常见的情况。

  1. WhereSelectArrayIterator不使用阵列的底层枚举 - 它使用索引。从性能角度看,最好直接使用数组索引器,而不是使用索引器或使用枚举器。

  2. WhereSelectListIterator确实使用列表的枚举,而是因为它“知道” List<TSource>枚举类型是结构List<TSource>.Enumerator(它可以检索使用特殊的GetEnumerator方法上List<TSource>从接口方法分离),它可以避免在堆上枚举枚举器 - 如果使用IEnumerator<TSource>,则必须执行该操作。

  3. WhereSelectEnumerableIterator是使用源的备份IEnumerator<TSource>的一般情况 - 它适用于所有种类的序列,但没有任何特殊的优化。如果枚举器恰好是一个结构体,那么运气不好 - 它会被装箱。

+0

是啊,我几分钟前就明白了。所以如果同一个想法在同一时间出现在不同的人身上,可能是对的。 –

相关问题