gpt4 book ai didi

c# - Skip 的性能(以及类似的功能,如 Take)

转载 作者:IT王子 更新时间:2023-10-29 04:35:12 28 4
gpt4 key购买 nike

我刚刚查看了 Skip 的源代码/Take .NET Framework 的扩展方法(在 IEnumerable<T> 类型上),发现内部实现正在使用 GetEnumerator方法:

// .NET framework
public static IEnumerable<TSource> Skip<TSource>(this IEnumerable<TSource> source, int count)
{
if (source == null) throw Error.ArgumentNull("source");
return SkipIterator<TSource>(source, count);
}

static IEnumerable<TSource> SkipIterator<TSource>(IEnumerable<TSource> source, int count)
{
using (IEnumerator<TSource> e = source.GetEnumerator())
{
while (count > 0 && e.MoveNext()) count--;
if (count <= 0)
{
while (e.MoveNext()) yield return e.Current;
}
}
}

假设我有一个 IEnumerable<T>有 1000 个元素(基础类型是 List<T> )。如果我正在执行 list.Skip(990).Take(10) 会发生什么?它会在取最后十个元素之前遍历 990 个第一个元素吗? (这就是我的理解)。如果是,那么我不明白为什么 Microsoft 没有实现 Skip像这样的方法:

    // Not tested... just to show the idea
public static IEnumerable<T> Skip<T>(this IEnumerable<T> source, int count)
{
if (source is IList<T>)
{
IList<T> list = (IList<T>)source;
for (int i = count; i < list.Count; i++)
{
yield return list[i];
}
}
else if (source is IList)
{
IList list = (IList)source;
for (int i = count; i < list.Count; i++)
{
yield return (T)list[i];
}
}
else
{
// .NET framework
using (IEnumerator<T> e = source.GetEnumerator())
{
while (count > 0 && e.MoveNext()) count--;
if (count <= 0)
{
while (e.MoveNext()) yield return e.Current;
}
}
}
}

事实上,他们这样做是为了 Count方法例如...

    // .NET Framework...
public static int Count<TSource>(this IEnumerable<TSource> source)
{
if (source == null) throw Error.ArgumentNull("source");

ICollection<TSource> collectionoft = source as ICollection<TSource>;
if (collectionoft != null) return collectionoft.Count;

ICollection collection = source as ICollection;
if (collection != null) return collection.Count;

int count = 0;
using (IEnumerator<TSource> e = source.GetEnumerator())
{
checked
{
while (e.MoveNext()) count++;
}
}
return count;
}

那是什么原因呢?

最佳答案

在 Jon Skeet 的优秀教程中重新实现 Linq ,他(简短地)讨论了这个问题:

Although most of these operations can't be sensibly optimized, itwould make sense to optimize Skip when the source implements IList.We can skip the skipping, so to speak, and go straight to theappropriate index. This wouldn't spot the case where the source wasmodified between iterations, which may be one reason it's notimplemented in the framework as far as I'm aware.

这似乎是推迟优化的合理理由,但我同意对于特定情况,如果您可以保证您的源不能/不会被修改,那么进行优化可能是值得的。

关于c# - Skip 的性能(以及类似的功能,如 Take),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20002975/

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