سؤال

هل هناك طريقة لاستخدام كتل العائد لتنفيذ IEnumerator<T> التي يمكن العودة إلى الوراء (MoveLast())، وكذلك إلى الأمام؟

هل كانت مفيدة؟

المحلول

وليس مباشرة من كتلة مكرر، لا.

ومع ذلك، فإن المتصل يمكن العازلة دائما النتائج، على سبيل المثال في List<T>، أو مجرد دعوة Reverse() - ولكن هذا لا ينطبق دائما

.

نصائح أخرى

لا، آلة الدولة التي تم إنشاؤها بواسطة C # مترجم بشكل صارم إلى الأمام.

وبل لا معنى للذهاب الى الوراء في كثير من الحالات. تخيل مكرر القراءة من تيار الشبكة - للذهاب الى الوراء، فإنه سيتعين عليها أن تتذكر كل شيء أنه قد قرأ من أي وقت مضى، لأنه لا يمكن إرجاع الوقت ومطالبة الشبكة للبيانات مرة أخرى

.

و(كما سبق أي شيء التي ولدت البيانات في بعض الطريق الضياع تخيل مكرر التي عادت مجلس إدارة جديد للحياة كونواي على كل التكرار - هناك لوحات متعددة والتي يمكن أن يكون جميع <م> سابقة واحد، لذلك لنعود إلى الوراء لديك مرة أخرى لتذكر ما كنت قد عادوا بالفعل).

وأنا أعرف هذا الموضوع هو السوبر القديم ولكن من المناسب الإشارة إلى أن

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

... والحصول على تجميعها في:

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

وحتى إذا كنت لا تمانع في بناء الجملة "MOVENEXT"، يمكن بسهولة تنفيذ IEnumerator وإضافة "MovePrevious". أنت لن تكون قادرة على عكس الاتجاه إذا كنت تستخدم "foreach" ولكنك تريد ان تكون قادرة على عكس الاتجاه في حالة استخدام حلقة while.

وأو ... إذا كنت ترغب في "foreach" قائمة في الاتجاه المعاكس (لا ثنائية الاتجاه) هل يمكن الاستفادة من العائد بيان.

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];
}

وأو ... إذا كنت تريد أن foreach في الاتجاه المعاكس من خلال تسير في الطريق الطويل يمكنك تطبيق بنفسك 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; }
    }
}

ولا. واحدة من القيود المفروضة على IEnumerator هو أنه يحمل وضعها الحالي، وأنها لا تذكر حالته السابقة. ونتيجة لذلك، IEnumerable هو إلى الأمام فقط.

إذا كنت بحاجة إلى التمسك الدول السابقة، وقراءة IEnumerable إلى قائمة أو قائمة متصلة وتعداد من خلال تلك الأشياء بدلا من ذلك.

ولا. باستخدام yield النتائج في <لأ href = "HTTP: // msdn.microsoft.com/en-us/library/9k7k7cf0.aspx "يختلط =" نوفولو noreferrer "> IEnumerable وهو أحادي الاتجاه.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top