我正在检查反射器中的代码,但我还没有找到它如何通过向后枚举集合?
由于没有计数信息,枚举总是从集合的“开始”开始,对吧?
这是.NET框架中的缺点吗?成本是否高于常规枚举?
答案 0 :(得分:41)
简而言之,它会缓冲一切,然后向后走。效率不高,但从那个角度来看,OrderBy也不是。
在LINQ-to-Objects中,有缓冲操作(Reverse,OrderBy,GroupBy等)和非缓冲操作(Where,Take,Skip等)。
作为使用Reverse
的非缓冲IList<T>
实施的示例,请考虑:
public static IEnumerable<T> Reverse<T>(this IList<T> list) {
for (int i = list.Count - 1; i >= 0; i--) {
yield return list[i];
}
}
请注意,如果你在迭代它时改变列表,这仍然有点容易受到错误...所以不要这样做;-p
答案 1 :(得分:6)
它通过复制底层IEnumerable&lt; T&gt;来工作。到一个数组,然后向后枚举该数组。 如果底层IEnumerable&lt; T&gt;实现ICollection&lt; T&gt; (如T [],List&lt; T&gt;等),然后跳过复制步骤,枚举器直接迭代底层集合。
有关更多信息,请查看System.Linq.Buffer&lt; TElement&gt;在Reflector。
编辑:始终复制基础集合,即使它是ICollection&lt; TElement&gt;。这可以防止底层集合中的更改被缓冲区&lt; TElement&gt;传播。
答案 2 :(得分:3)
它将所有项目加载到内存中,然后逐步执行(向后)。效率低得多。
答案 3 :(得分:-3)
编辑:Opps,为反向写了错误的测试,我为错误答案道歉。它在校正测试后会缓冲(使用Reverse()返回的枚举
)看起来反向扩展方法仅在填充集合时有效。在使用收益率回报时,它没有做任何事情。
使用反向思考进入问题它必须缓冲它才能工作,发现它不适用于yield。它只是通过它,不做任何事情。下面是我的测试代码。
[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;
}
}
反向根本不调用GetSeries函数,本论坛中的所有缓冲区会话都是空气稀薄。