gpt4 book ai didi

c# - 为 IList 优化 LINQ

转载 作者:太空狗 更新时间:2023-10-29 17:57:38 26 4
gpt4 key购买 nike

不久前,我编写了一个IList 扩展方法,通过使用索引来枚举列表的一部分。在重构时,我意识到可以通过调用 Skip(toSkip).Take(amount) 来执行类似的查询。在对此进行基准测试时,我注意到 Skip 并未针对 IList 进行优化。通过一些谷歌搜索,我最终找到了 Jon Skeet 的帖子,discussing why optimizing methods like Skip is dangerous .

据我对这篇文章的理解,问题是在修改集合时优化的方法中没有抛出异常,但正如评论所述,msdn 文档本身存在冲突。

IEnumerator.MoveNext() :

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.

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.

我看到了这两个约定的优点,并且不知道是否要优化。什么是正确的解决方案?正如 Kris Vandermotten 在评论中提到的那样,我一直在考虑 IList.AssumeImmutable() 方法,该方法与 AsParallel() 类似。是否已经存在任何实现,或者这是一个坏主意?

最佳答案

我同意 Rafe 的观点,未定义的行为更正确。只有版本化的集合可以抛出异常,并不是所有的集合都是版本化的(数组是最大的例子)。如果您在对 MoveNext 的调用之间恰好进行 2^32 次更改,即使是版本化的集合也可能会出现异常。

假设您真的关心版本控制行为,解决方案是为 IList 获取一个 Enumerator 并为每个调用它调用 MoveNext迭代:

    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;我们忽略它正在枚举的值。

关于c# - 为 IList 优化 LINQ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5862503/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com