理解扩展 ElementAt(index)

发布于 2024-09-08 16:50:15 字数 509 浏览 4 评论 0原文

考虑这段代码:

int size = 100 * 1000 * 1000;
var emu = Enumerable.Range(0, size);
var arr = Enumerable.Range(0, size).ToArray();

当我调用 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)

,并且由于“源”是 IEnumerable,因此执行的逻辑将类似 - 与我所看到的直接访问数组的情况相反。

有人可以解释一下吗:)

Consider this code:

int size = 100 * 1000 * 1000;
var emu = Enumerable.Range(0, size);
var arr = Enumerable.Range(0, size).ToArray();

when I call emu.ElementAt(size-10) and arr.ElementAt(size-10) and measure the time the arr is much faster (the array is 0.0002s compared to IEnumerable 0.59s).

As I understand it, the extention method ElementAt() have the signature

public static TSource ElementAt<TSource>(this IEnumerable<TSource> source, int index)

and since the 'source' is a IEnumerable the logic carried out would be similar - opposed to what I see where the array is accessed directly.

Could someone please explain this :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

旧城空念 2024-09-15 16:50:15

IEnumerable 上调用 ElementAt 将循环遍历项目,直到到达所需的索引。 (O(n) 操作)

IList(例如数组)上调用 ElementAt 将使用 IList的索引器立即获得所需的索引。 (O(1) 操作)

Calling ElementAt on an IEnumerable<T> will loop through the items until it reaches the desired index. (An O(n) operation)

Calling ElementAt on an IList<T> (such as an array) will use the IList<T>'s indexer to immediately get the desired index. (An O(1) operation)

下雨或天晴 2024-09-15 16:50:15

这是在执行时执行的优化。尽管调用未重载,但它可以检查(使用 isas)源是否实际上是 IList 。如果是,它就能够直接转到正确的元素。

其他各种调用都可以执行此操作 - 值得注意的是 Count(),它针对 ICollection 和(从 .NET 4 开始)非泛型 ICollection 进行了优化界面。

扩展方法的缺点之一是所有这些优化都必须由实现本身执行 - 类型不能覆盖任何内容来“选择加入”优化扩展方法。这意味着原始实现者必须知道所有优化:(

This is an optimization performed at execution-time. Although the call isn't overloaded, it is able to check (using is or as) whether the source is actually an IList<T>. If it is, it's able to go directly to the right element.

Various other calls do this - notable Count() which is optimised for ICollection<T> and (as of .NET 4) the nongeneric ICollection interface.

One of the downsides of extension methods is that all these optimizations have to be performed by the implementation itself - types can't override anything to "opt in" to optimizing extension methods. That means the optimizations have to all be known by the original implementor :(

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文