IEnumerator
は前方のみの反復子であるため、使用できません。MoveNext()
メソッドしかありません。これにより、インターフェイスは非常に普遍的になり、Linq のコアになります。storageが必要なため、逆方向に反復できない実世界のコレクションがたくさんあります。たとえば、ほとんどのストリームはそのようなものです。
Linq は、Reverse()
拡張メソッドを使用してソリューションを提供します。最初に要素を保存してから、逆方向に反復することで機能します。ただし、これは非常に無駄になる可能性があり、O(n) ストレージが必要です。すでにインデックス可能なコレクションの最適化の可能性がありません。あなたが修正できるもの:
static class Extensions {
public static IEnumerable<T> ReverseEx<T>(this IEnumerable<T> coll) {
var quick = coll as IList<T>;
if (quick == null) {
foreach (T item in coll.Reverse()) yield return item;
}
else {
for (int ix = quick.Count - 1; ix >= 0; --ix) {
yield return quick[ix];
}
}
}
}
使用例:
var list = new List<int> { 0, 1, 2, 3 };
foreach (var item in list.ReverseEx()) {
Console.WriteLine(item);
}
LinkedList は実装されていませんが、およびプロパティIList<T>
を介して迅速な後方反復が可能であるため、特殊化する必要があります。そのクラスを使用しない方がはるかに優れていますが、CPU キャッシュの局所性が貧弱です。安価なインサートが必要ない場合は、常にお勧めします。次のようになります。Last
LinkedListNode.Previous
List<T>
public static IEnumerable<T> ReverseEx<T>(this LinkedList<T> list) {
var node = list.Last;
while (node != null) {
yield return node.Value;
node = node.Previous;
}
}