跳跃的性能(和类似的功能,喜欢拍摄) [英] Performance of Skip (and similar functions, like Take)

查看:114
本文介绍了跳跃的性能(和类似的功能,喜欢拍摄)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我只是看看源$ C ​​$ c中的跳过 / 的扩展方法.NET框架(在的IEnumerable< T> 键入),发现内部实现与的GetEnumerator 方法工作

I just had a look at the source code of the Skip/Take extension methods of the .NET Framework (on the IEnumerable<T> type) and found that the internal implementation is working with the GetEnumerator method:

// .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&LT; T&GT; 1000元(基本类型是列表&LT; T&GT; ) 。如果我做list.Skip(990)。取(10)会发生什么?它会遍历througt走过去的十年前的990第一要素? (这是我的理解)。如果是的话,那么我不明白为什么微软没有实现这样的跳过方法:

Suppose that I have an IEnumerable<T> with 1000 elements (underlying type is List<T>). What happens if I'm doing list.Skip(990).Take(10) ? Will it iterate througt the 990 first elements before taking the last ten? (this is how I understand it). If yes, then I don't understand why Microsoft didn't implement the Skip method like this:

    // 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;
                }
            }
        }
    }

在事实上,他们这样做的计数方法,例如...

In fact, they did that for the Count method for example...

    // .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;
    } 

所以,有什么原因呢?

So what's the reason?

推荐答案

在乔恩斯基特的优秀教程重新实施<一个href=\"https://msmvps.com/blogs/jon_skeet/archive/2011/01/02/reimplementing-linq-to-objects-part-23-take-skip-takewhile-skipwhile.aspx\">Linq,他讨论了(暂时的)这个问题了:

In Jon Skeet's excellent tutorial re-implementing Linq, he discusses (briefly) that very question:

尽管大多数这些操作不能合理地优化,它
  将是有意义的优化跳过当源实现IList。
  我们可以跳过跳绳,可以这么说,并直接进入
  适当的索引。这不会发现其中源是事实
  迭代,这可能是一个原因之间修改它不是
  在该框架就我所知实现的。

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

这似乎是一个合理的理由推迟了优化,但我同意,具体的情况下,它可能是值得做的优化,如果你能保证你的源不能/不会被修改。

That seems like a reasonable reason to hold off on that optimization, but I agree that for specific cases, it may be worthwhile to make that optimization if you can guarantee your source can't/won't be modified.

这篇关于跳跃的性能(和类似的功能,喜欢拍摄)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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