【发布时间】:2011-08-17 06:39:33
【问题描述】:
不久前,我编写了一个IList 扩展方法,通过使用索引来枚举列表的一部分。在重构时,我意识到可以通过调用Skip(toSkip).Take(amount) 来执行类似的查询。在对此进行基准测试时,我注意到Skip 没有针对IList 进行优化。通过谷歌搜索,我最终找到了 Jon Skeet 的一个帖子,discussing why optimizing methods like Skip is dangerous。
据我对文章的理解,问题是在修改集合时优化方法中没有抛出异常,但作为评论指出msdn文档本身冲突。
如果对集合进行了更改, 例如添加、修改或删除 元素,枚举数是 不可恢复地失效和下一个 调用 MoveNext 或 Reset 会抛出一个 无效操作异常。
如果对集合进行了更改, 例如添加、修改或删除 元素,枚举数是 不可恢复的无效及其 行为未定义。
我看到了这两种约定的优点,对于是否优化有点迷茫。什么是合适的解决方案?正如 Kris Vandermotten 在 cmets 中提到的那样,我一直在考虑采用AsParallel() 的IList.AssumeImmutable() 方法。是否已经存在任何实现,或者这是一个坏主意?
【问题讨论】:
-
如果 Jon 得出结论认为优化
Skip等是错误的,并且有一段解释为什么......那么我会认为这是一个很好的理由。 -
我认为“未定义”语义比“抛出异常”语义更实用(尽管后者更可靠),仅仅是因为后者要求每个枚举器实例都能够测试修改主机容器。啊!
-
然而,Jon 的观点仍然成立。没有什么可以阻止您使用
Skip/Take编写ItemsInRange(Lo, Hi)枚举器没有。 -
@Rafe:我写了一个答案并删除了它,因为对称
ItemsInRange应该存在于IEnumerable并且会抛出,所以IList版本不能被优化乔恩的论点。 -
@Marc:我们怎么知道 Jon 在重新思考时是对的,而不是一开始就错了?
标签: c# .net linq optimization skip