LINQ:为什么数组和列表使用不同的迭代器

时间:2014-03-14 04:31:56

标签: c# .net performance 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>,所以它们都可以以相同的单一方式迭代,但现在使用不同的迭代器。

1 个答案:

答案 0 :(得分:5)

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

  1. WhereSelectArrayIterator不使用数组的基础枚举器 - 它使用索引器。从性能角度来看,最好直接使用数组索引器,而不是通过IList<T>索引器或使用枚举器。

  2. WhereSelectListIterator确实使用列表的枚举器,但因为它&#34;知道&#34; List<TSource>枚举器的类型是 struct List<TSource>.Enumerator(它可以使用与{1}}上的特殊GetEnumerator方法检索,与接口方法分开),它避免在堆上装入枚举器 - 如果使用List<TSource>,则必须执行此操作。

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