Mob*_*erg 5 c# linq extension-methods
考虑以下代码:
int size = 100 * 1000 * 1000;
var emu = Enumerable.Range(0, size);
var arr = Enumerable.Range(0, size).ToArray();
Run Code Online (Sandbox Code Playgroud)
当我调用emu.ElementAt(size-10)和arr.ElementAt(size-10)并测量arr更快的时间时(与IEnumerable 0.59s相比,数组为0.0002s).
据我了解,扩展方法ElementAt()具有签名
public static TSource ElementAt<TSource>(this IEnumerable<TSource> source, int index)
Run Code Online (Sandbox Code Playgroud)
并且因为'source'是IEnumerable,所执行的逻辑将是类似的 - 与我看到的直接访问数组的情况相反.
有人可以解释一下:)
SLa*_*aks 12
调用ElementAt一个IEnumerable<T>将循环遍历项目,直到达到所需的索引.(一个O(n)操作)
调用ElementAt上的IList<T>(例如阵列)将使用IList<T>的索引器立刻得到所需的索引.(一个O(1)操作)
这是在执行时执行的优化.虽然调用没有超载,但它能够检查(使用is或as)源是否实际上是IList<T>.如果是,它可以直接转到正确的元素.
各种其他调用都是这样做的 - 值得注意的Count()是针对ICollection<T>非通用ICollection接口和(从.NET 4开始)优化的非通用接口.
扩展方法的一个缺点是所有这些优化都必须由实现本身执行 - 类型不能覆盖任何"选择"优化扩展方法.这意味着原始实现者必须知道优化:(