IEnumerable .Reverse是如何工作的?

我正在检查reflection器中的代码,但我还没有发现它如何通过一个集合向后枚举?

由于没有计数信息,枚举总是从集合的“开始”开始,对吧?

它是.NET框架中的缺点吗? 成本是否高于常规枚举?

简而言之,它会缓冲所有内容,然后向后遍历它。 效率不高,但从那个角度来看,OrderBy也不是。

在LINQ-to-Objects中,有缓冲操作(Reverse,OrderBy,GroupBy等)和非缓冲操作(Where,Take,Skip等)。


作为使用IList的非缓冲Reverse实现的示例,请考虑:

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

请注意,如果在迭代时改变列表,这仍然有点容易受到错误…所以不要这样做;-p

它的工作原理是将底层IEnumerable 复制到一个数组,然后向后枚举该数组。 如果底层IEnumerable 实现ICollection (如T [],List 等),则跳过复制步骤,枚举器直接遍历底层集合。

有关更多信息,请查看Reflector中的System.Linq.Buffer

编辑:始终复制基础集合,即使它是ICollection 。 这可以防止底层集合中的更改被Buffer 传播。

它将所有项目加载到内存中,然后逐步执行(向后)。 效率低得多。

编辑:Opps,为反向写了错误的测试,我为错误的答案道歉。 校正测试后它会缓冲(使用Reverse()返回的枚举)

看起来反向扩展方法仅在填充集合时有效。 使用收益率回报时,它不会做任何事情。

使用反向思想进入问题它必须缓冲它才能工作,发现它不能用于产量。 它只是通过它,不做任何事情。 下面是我的测试代码。

  [TestMethod] public void loopTest() { var series = this.GetSeries(); series.Reverse(); foreach (var l in series) { Debug.WriteLine(l); } } private IEnumerable GetSeries() { var series = new List() { 1, 2, 3, 4 }; foreach (var entry in series) { Debug.WriteLine(entry); yield return entry; } } 

反向根本不调用GetSeries函数,这个论坛中的所有缓冲区会话都是空洞的。