簡體   English   中英

如何使我的InfiniteLoopingList類實現IEnumerable?

[英]How to make my InfiniteLoopingList class implement IEnumerable?

我正在制作一個原型應用程序,為此,我設計了一個行為類似於無限循環列表的類。 也就是說,如果我的內部列表包含100個值,則當我要求第101個值時,我得到第一個,第102個產生第二個,依此類推,重復進行。

所以我想寫下面的代碼:

var slice = loopingListInstance.Skip(123).Take(5);

據我所知,為此,我需要實現合適的IEnumerable。

這是我當前的代碼:

public class InfiniteLoopingList : IEnumerable<double>
{
    double[] _values = File.ReadLines(@"c:\file.txt")
                            .Select(s => double.Parse(s, CultureInfo.InvariantCulture))
                            .ToArray();
    int _size;

    public InfiniteLoopingList()
    {
        _size = _values.Length;
    }

    public double this[int i]
    {
        get { return _values[i % _size]; }
        set { _values[i % _size] = value; }
    }

    public IEnumerator<double> GetEnumerator()
    {
        return this.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        // ???? now what ?? :(
    }
}

由於實現了indexer屬性,因此可以通過以下最簡單的方法進行操作:

public IEnumerator<double> GetEnumerator()
{
    int i = 0;
    while (true)
        yield return this[i++];
}

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

編輯
請注意,這並不是真正的無限循環。 該方法僅在i = int.MaxValue之前i = int.MaxValue 感謝@oleksii。

您不需要為此上課...

擴展方法可以解決這個問題:

public static class InfEx
{
    public static IEnumerable<T> LoopForever<T>(this IEnumerable<T> src)
    {
        var data = new List<T>();
        foreach(var item in src)
        {
            data.Add(item);
            yield return item;
        }

        for(;;)
        {
            foreach(var item in data)
            {
                yield return item;
            }
        }
    }
}

現在,您可以采用一個序列並將其設為循環的無限序列:

IEnumerable<Foo> mySeq = ...;
IEnumerable<Foo> infMySeq = mySeq.LoopForver();
IEnumerable<Foo> aSelectionOfInfMySeq = infMySeq.Skip(101).Take(5);

您可以實現IEnumerator接口:

class InifniteEnumerator<T> : IEnumerator<T> {        
    private int index = -1;
    private IList<T> innerList;
    private int repeatPos;
    public InifniteEnumerator(IList<T> innerList, int repeatPos) {
        this.innerList = innerList;
        this.repeatPos = repeatPos;
    }
    public T Current {
        get {
            if (index == -1) {
                throw new InvalidOperationException();
            }
            return this.innerList[index];
        }
    }
    object IEnumerator.Current {
        get {
            return this.Current;
        }
    }
    public void Dispose() {

    }
    public bool MoveNext() {
        this.index++;
        if (this.index == repeatPos) {
            this.index = 0;
        }
        return true;
    }
    public void Reset() {
        this.index = -1;
    }
}

然后在GetEnumerator方法中返回它的一個實例:

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

public IEnumerator<T> IEnumerable<T>.GetEnumerator() {
    return new InifniteEnumerator(this, 100);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM