Frage

Gibt es eine Möglichkeit Ausbeute Blöcke zu verwenden, um ein IEnumerator<T> zu implementieren, die rückwärts gehen können (MoveLast()) sowie nach vorn?

War es hilfreich?

Lösung

Nicht direkt aus dem Iteratorblock, Nr.

Allerdings kann der Anrufer immer die Ergebnisse Puffer, zum Beispiel in eine List<T>, oder einfach nur Reverse() nennen - aber das ist nicht immer gilt

.

Andere Tipps

Nein, die Zustandsmaschine durch den C # Compiler erzeugt wird streng nach vorne.

Es ist nicht einmal Sinn machen, in vielen Fällen gehen rückwärts. Stellen Sie sich einen Iterator aus einem Netzwerk-Stream zu lesen - rückwärts zu gehen, hätte es alles erinnern, dass es jemals gelesen hatte, weil es nicht an der Zeit zurückspulen könnte und fragen Sie das Netzwerk für die Daten wieder

.

(Ditto alles, was Daten in einigen verlustbehafteten Weise erzeugt Stellen Sie sich einen Iterator, die bei jeder Iteration einen neuen Vorstand für Conways Leben zurückgekehrt -. Gibt es mehrere Platten, die alle eine der zurück gewesen sein könnte, so Sie müssen wieder rückwärts gehen daran erinnern, was Sie bereits zurückgegeben.)

Ich weiß, dass dieser Thread Super alt ist, aber es ist relevant zu beachten, dass

foreach(var item in someCollection)
{
    // Do something
}

... wird kompiliert und in der sie:

var enumerator = someCollection.GetEnumerator()
while (enumerator.MoveNext())
{
    var item = enumerator.Current;
    // Do something
}

Wenn Sie also nicht die „Movenext“ Syntax nichts ausmacht, könnte man leicht IEnumerator implementieren und eine „MovePrevious“ hinzufügen. Sie würden nicht in der Lage sein, die Richtung umzukehren, wenn Sie „foreach“ verwenden, aber Sie wäre in der Lage Richtung umkehrt, wenn eine while-Schleife verwendet wird.

oder ... wenn Sie möchten, eine Liste in umgekehrter Richtung „foreach“ (nicht bidirektional) Sie Vorteil der Ertragsrechnung nehmen könnten.

public static IEnumerable<TItem> Get<TItem>(IList<TItem> list)
{
    if (list == null)
        yield break;

    for (int i = list.Count - 1; i > -1; i--)
        yield return list[i];
}

oder ... wenn Sie wollen, in umgekehrter Richtung foreach durch den langen Weg gehen können Sie implementieren Ihre eigenen IEnumerable / IEnumerator

public static class ReverseEnumerable
{
    public static IEnumerable<TItem> Get<TItem>(IList<TItem> list)
    {
        return new ReverseEnumerable<TItem>(list);
    }
}

public struct ReverseEnumerable<TItem> : IEnumerable<TItem>
{
    private readonly IList<TItem> _list;

    public ReverseEnumerable(IList<TItem> list)
    {
        this._list = list;
    }

    public IEnumerator<TItem> GetEnumerator()
    {
        if (this._list == null)
            return Enumerable.Empty<TItem>().GetEnumerator();

        return new ReverseEnumator<TItem>(this._list);
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
}

public struct ReverseEnumator<TItem> : IEnumerator<TItem>
{
    private readonly IList<TItem> _list;
    private int _currentIndex;

    public ReverseEnumator(IList<TItem> list)
    {
        this._currentIndex = list.Count;
        this._list = list;
    }

    public bool MoveNext()
    {
        if (--this._currentIndex > -1)
            return true;

        return false;
    }

    public void Reset()
    {
        this._currentIndex = -1;
    }

    public void Dispose() { }

    public TItem Current
    {
        get
        {
            if (this._currentIndex < 0)
                return default(TItem);

            if (this._currentIndex >= this._list.Count)
                return default(TItem);

            return this._list[this._currentIndex];
        }
    }

    object IEnumerator.Current
    {
        get { return this.Current; }
    }
}

C5 Sammlungen Bibliothek ( http://www.itu.dk/research/c5/) implementiert Sammlungen und verknüpfte Liste mit rückwärts Aufzählung. Das Projekt ist Open Source, so sollten Sie in der Lage sein, dort zu finden beantworten.

Nein. Eine der Einschränkungen von IEnumerator ist, dass es seinen aktuellen Zustand hält, und sie erinnert sich nicht an seinen vorherigen Zustand. Als Ergebnis ist IEnumerable zukunfts nur.

Wenn Sie auf vorherige Zustände zu halten, lesen Sie die IEnumerable in eine Liste oder LinkedList und aufzuzählen, durch diese Objekte statt.

Eigentlich scheint es in Accelerated C # 2008 . Leider sind zwei Seiten in der Vorschau nicht sichtbar, und es hat auf Reflexion (deren Ergebnisse zwischengespeichert werden können, wie üblich) verlassen, aber man kann das Wesentliche bekommen.

Nein. Mit yield führt zu einem IEnumerable das ist unidirektional.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top