简体   繁体   中英

How to make my InfiniteLoopingList class implement IEnumerable?

I am making a prototype application and for that I designed a class that behaves like an infinite looping list. That is, if my internal list contains 100 values, when I ask for the 101st value, I get the first, the 102nd yields the second, and so on, repeating.

So I would like to write the following code:

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

And for that I need to implement IEnumerable suitable, as I understand.

Here is my current code:

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 ?? :(
    }
}

Since you implemented the indexer property, you could do it via the simplest way as follows:

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

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

EDIT
Please notice, that this is not really infinite loop. This approach will only work until i = int.MaxValue . Thanks to @oleksii.

You don't need a class for this...

An extension method will do the trick:

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

Now you can take a sequence and make it a looping, infinite sequence:

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

You can implement the IEnumerator interface:

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

and then return an instance of it in the GetEnumerator methods:

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM