简体   繁体   English

IEnumerable怎么样? <T> 反向工作?

[英]How does IEnumerable<T>.Reverse work?

I am checking out the code in the reflector, but I haven't yet found out how it can enumerate through a collection backwards? 我正在检查反射器中的代码,但我还没有发现它如何通过集合向后枚举?

Since there is no count information, and enumeration always starts from the "start" of the collection, right? 由于没有计数信息,枚举总是从集合的“开始”开始,对吧?

Is it a drawback in the .NET framework? 这是.NET框架中的缺点吗? Is the cost higher than regular enumeration? 成本是否高于常规枚举?

In short, it buffers everything and then walks through it backwards. 简而言之,它会缓冲所有内容,然后向后穿过它。 Not efficient, but then, neither is OrderBy from that perspective. 效率不高,但从那个角度来看,OrderBy也不是。

In LINQ-to-Objects, there are buffering operations (Reverse, OrderBy, GroupBy, etc) and non-buffering operations (Where, Take, Skip, etc). 在LINQ-to-Objects中,有缓冲操作(Reverse,OrderBy,GroupBy等)和非缓冲操作(Where,Take,Skip等)。


As an example of a non-buffering Reverse implementation using IList<T> , consider: 作为使用IList<T>的非缓冲Reverse实现的示例,请考虑:

public static IEnumerable<T> Reverse<T>(this IList<T> list) {
    for (int i = list.Count - 1; i >= 0; i--) {
        yield return list[i];
    }
}

Note that this is still a little susceptible to bugs if you mutate the list while iterating it... so don't do that ;-p 请注意,如果在迭代时改变列表,这仍然有点容易受到错误...所以不要这样做;-p

It works by copying the underlying IEnumerable<T> to an array, then enumerating over that array backward. 它的工作原理是将底层的IEnumerable <T>复制到一个数组,然后向后枚举该数组。 If the underlying IEnumerable<T> implements ICollection<T> (like T[], List<T>, etc.), then the copy step is skipped and the enumerator just iterates over the underlying collection directly. 如果底层IEnumerable <T>实现ICollection <T>(如T [],List <T>等),则跳过复制步骤,枚举器直接遍历底层集合。

For more information, check out System.Linq.Buffer<TElement> in Reflector. 有关更多信息,请查看Reflector中的System.Linq.Buffer <TElement>。

Edit: The underlying collection is always copied, even if it's an ICollection<TElement>. 编辑:始终复制基础集合,即使它是ICollection <TElement>。 This prevents changes in the underlying collection from being propagated by the Buffer<TElement>. 这可以防止底层集合中的更改被Buffer <TElement>传播。

it loads all items to memory and then steps through them (backwards). 它将所有项目加载到内存中,然后逐步执行(向后)。 this is far less efficient. 效率低得多。

Edit: Opps, wrote wrong test for reverse, my apology for wrong answer. 编辑:Opps,为反向写了错误的测试,我为错误的答案道歉。 It does buffer after correcting test(using enumerable returned by Reverse()) 校正测试后它会缓冲(使用Reverse()返回的枚举)

Looks like Reverse extension method only works when collection is populated. 看起来反向扩展方法仅在填充集合时有效。 While using yield return it does not do anything. 使用收益率回报时,它不会做任何事情。

Ran into problem using reverse thought it must buffer for it to work, found it does not work with yield. 使用反向思想进入问题它必须缓冲它才能工作,发现它不能用于产量。 It just go pass it and don't do anything. 它只是通过它,不做任何事情。 below is my test code. 下面是我的测试代码。

        [TestMethod]
    public void loopTest()
    {
        var series = this.GetSeries();

        series.Reverse();

        foreach (var l in series)
        {
            Debug.WriteLine(l);
        }
    }

    private IEnumerable<long> GetSeries()
    {
        var series = new List<long>() { 1, 2, 3, 4 };

        foreach (var entry in series)
        {
            Debug.WriteLine(entry);

            yield return entry;
        }
    }

Reverse do not call GetSeries function at all, all buffer talks in this forum looks from thin air. 反向根本不调用GetSeries函数,这个论坛中的所有缓冲区会话都是空气稀薄。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM