17

C# に逆列挙子を含めないという特定の理由または設計上の決定があったかどうかは誰にもわかりませんか? reverse_iteratorEnumerator が C++ に相当するのと同じように、 C++ に相当するものがあれば、とてもいいでしょうiterator。逆に反復できるコレクションは、 IReverseEnumerable のようなものを実装するだけで、次のようなことができます。

List<int>.ReverseEnumerator ritr = collection.GetReverseEnumerator();
while(rtir.MoveNext())
{
 // do stuff
}

このようにして、一方にインデクサーを使用し、もう一方に前のリンクを使用するのではなく、リストと LinkedList を同じ方法で反復処理できるため、より優れた抽象化を実現できます。

4

4 に答える 4

21

これを実装することは完全に可能です。個人的には、リバース イテレーションを行うことはほとんどありません。これを行う必要がある場合は、最初に .Reverse() を呼び出します。おそらくこれは、.NET BCL の設計者も同様に考えたことでしょう。

デフォルトでは、すべての機能が実装されていません。それらは、設計、実装、テスト、文書化、およびサポートされる必要があります。- レイモンド・チェン

これが、ほとんど役に立たない機能を実装しない理由です。最も重要な機能から始めます (前から後ろへの反復など)。そして、予算が使い果たされた場所、または続行する意味がないと思われる場所で停止します。

.NET 基本クラス ライブラリにないものがたくさんあります。.NET 4 までは、.NET さえありませんでしたFile.EnumerateLines。そして、ほとんどの人にとって、そのような機能は逆の反復よりも重要であると思い切って言います。

逆の繰り返しが一般的なビジネス ドメインで作業している場合があります。私の経験は反対です。フレームワークの設計者として、誰があなたのフレームワークを使用し、それらの人々がどのような機能を要求するかを推測することしかできません。線引きが難しい。

于 2012-02-17T23:54:02.943 に答える
15

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 キャッシュの局所性が貧弱です。安価なインサートが必要ない場合は、常にお勧めします。次のようになります。LastLinkedListNode.PreviousList<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;
        }
    }
于 2012-02-18T13:59:43.883 に答える