优化LINQ的IList的 [英] Optimize LINQ for IList

查看:195
本文介绍了优化LINQ的IList的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

前一段时间我写了的IList 扩展方法,通过使用索引整个列表的一部分枚举。虽然重构我实现了一个类似的查询可以通过调用执行跳过(toSkip)。取(量)。虽然这个基准测试,我注意到不为的IList 优化。带着几分谷歌搜索的,我结束了在乔恩斯基特后,<一个href="https://msmvps.com/blogs/jon_skeet/archive/2011/01/26/reimplementing-linq-to-objects-part-40-optimization.aspx"相对=nofollow>讨论为什么优化方法,如跳过是危险。

A while ago I wrote an IList extension method to enumerate across part of a list by using the indices. While refactoring I realized a similar query could be performed by calling Skip(toSkip).Take(amount). While benchmarking this I noticed that Skip isn't optimized for IList. With a bit of googling I ended up at a Jon Skeet post, discussing why optimizing methods like Skip is dangerous.

据我理解文章,问题是不会抛出异常的优化方法,当集合被修改,但作为一个注释状态MSDN文档冲突本身。

As far as I understand the article, the problem is no exception is thrown in the optimized methods when the collection is modified, but as a comment states the msdn documentation conflicts itself.

IEnumerator.MoveNext()

如果更改了收集,   例如添加,修改或删除   元素,枚举是   失效且不可恢复,并且下一个   呼吁对MoveNext或Reset 引发   InvalidOperationException异常。

If changes are made to the collection, such as adding, modifying, or deleting elements, the enumerator is irrecoverably invalidated and the next call to MoveNext or Reset throws an InvalidOperationException.

在<一个href="http://msdn.microsoft.com/en-us/library/system.collections.ienumerable.getenumerator.aspxundefined"相对=nofollow> IEnumerator.GetEnumerator():

如果更改了收集,   例如添加,修改或删除   元素,枚举是   失效且不可恢复,其   行为的未定义

If changes are made to the collection, such as adding, modifying, or deleting elements, the enumerator is irrecoverably invalidated and its behavior is undefined.

我看在这两个公约的优点,并感到有点失落是否要优化。什么是一个妥善的解决办法?我一直在考虑沿的行的 IList.AssumeImmutable()办法进行AsParallel()所提到的克里斯Vandermotten在意见。是否有实施已经存在,或者是一个坏主意?

I see merit in both conventions, and am a bit lost whether or not to optimize. What is a proper solution? I've been considering an IList.AssumeImmutable() approach along the lines of AsParallel() as mentioned by Kris Vandermotten in the comments. Does any implementation already exist, or is it a bad idea?

推荐答案

我同意雷夫的未定义行为是比较正确的。只有版本的集合可以抛出异常,而不是所有的集合版本(数组是最大的例子)。如果你拨打电话的正是2 ^ 32变为的MoveNext 即使版本集可能会表现不好。

I agree with Rafe that the undefined behavior is more correct. Only versioned collections can throw exceptions and not all collections are versioned (arrays being the largest example). Even versioned collections might misbehave if you make exactly 2^32 changes between calls to MoveNext.

假设你真正关心的版本问题,解决的办法是让一个枚举的IList 和呼叫的MoveNext 于它的每次迭代:

Assuming you really care about the versioning behavior, the solution is to get an Enumerator for the IList and call MoveNext on it for every iteration:

    public static IEnumerable<T> Skip<T>(this IList<T> source, int count)
    {
        using (var e = source.GetEnumerator())
            while (count < source.Count && e.MoveNext())
                yield return source[count++];
    }

这样你得到的O(1)行为通过索引,但你仍然可以调用所有的异常抛出的行为的MoveNext 。需要注意的是,我们只调用的MoveNext 为异常的副作用;我们忽略了它的枚举所有的值。

This way you get O(1) behavior by indexing, but you still get all the exception throwing behavior of calling MoveNext. Note that we only call MoveNext for the exception side-effects; we ignore the values that it's enumerating over.

这篇关于优化LINQ的IList的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆