0

I am looking for a data structure that I can fill with items, and like an IEnumerator call MoveNext() but when it gets to the end of the list automatically loop back to the beginning. I can think of two ways to do this, either use a linked list and link it to itself, or just write the logic to check if IEnumerator.Current is null and reset, both rather trivial to write but I wanted to first check if there was something in the framework that already can do this.

It would look something like this:

public interface IInfiniteEnumerable<T>
{
    bool MoveNext();

    T Current();
}

Edit: As per the answer this does the trick:

class Program
{
    static void Main(string[] args)
    {
        var lst = new List<string>
        {
            "A",
            "B",
            "C"
        };

        IEnumerator<string> enumerator = lst.RepeatIndefinitely().GetEnumerator();

        Console.WriteLine(enumerator.Current);
        enumerator.MoveNext();
        Console.WriteLine(enumerator.Current);
        enumerator.MoveNext();
        Console.WriteLine(enumerator.Current);
        enumerator.MoveNext();
        Console.WriteLine(enumerator.Current);
        enumerator.MoveNext();
        Console.WriteLine(enumerator.Current);
        enumerator.MoveNext();
        Console.WriteLine(enumerator.Current);
        enumerator.MoveNext();
        Console.WriteLine(enumerator.Current);
        enumerator.MoveNext();
        Console.WriteLine(enumerator.Current);
        enumerator.MoveNext();
        Console.WriteLine(enumerator.Current);
        enumerator.MoveNext();
        Console.WriteLine(enumerator.Current);

        Console.ReadLine();
    }
}

public static class Extensions
{
    public static IEnumerable<T> RepeatIndefinitely<T>(this IEnumerable<T> source)
    {
        while (true)
        {
            foreach (var item in source)
            {
                yield return item;
            }
        }
    }
}
Eric Scherrer
  • 3,328
  • 1
  • 19
  • 34
  • 1
    Why do you need to do this? And an Enumerable has to have an end, so an Infinite Enumerable breaks that format. – gunr2171 Jun 17 '14 at 19:41
  • circular linked list, but you have to implement it yourself, which is not that difficult – AD.Net Jun 17 '14 at 19:41
  • btw, MoveNext() returns a bool, not void. – Dennis_E Jun 17 '14 at 19:42
  • @unr2171 In the UI have to loop through some messages continuously, when reach the end go back to the beginning. – Eric Scherrer Jun 17 '14 at 19:43
  • 1
    Duplicate of http://stackoverflow.com/questions/24181656 perhaps? – Jon Skeet Jun 17 '14 at 19:46
  • 2
    @gunr2171 "An enumerable has to have an end" Why? Is this documented as part of the interface? – Asad Saeeduddin Jun 17 '14 at 19:50
  • @Asad, how are you going to call `.Sum()` on something that will never end? – gunr2171 Jun 17 '14 at 19:50
  • @JonSkeet Simiar except that seems like a firehose, I need a water fountain with a "give me more" button. – Eric Scherrer Jun 17 '14 at 19:50
  • Well no, it's still an `IEnumerable`... it waits for you to fetch the data from it. Put it this way - if it's *not* a duplicate, then I don't know what your question is asking. – Jon Skeet Jun 17 '14 at 19:51
  • @gunr2171, you wouldn't. But that doesn't mean an enumerable *has* to end, or even be performant when returning aggregates such as Sum. – Anthony Pegram Jun 17 '14 at 19:52
  • @gunr2171 There are some operations that can be performed on an infinite sequence, and some that can't. The fact that some operations cannot be applied to infinite sequences doesn't mean *none* of them can, or that you should never ever use them. It simply means you need to be careful when using them and consider whether the operation in question can properly support infinite sequences. – Servy Jun 17 '14 at 19:52
  • @JonSkeet Ok I get it, let me give that a try. Will delete question shortly. – Eric Scherrer Jun 17 '14 at 19:56
  • @gunr2171 I'm pretty sure `Sum` is a LINQ extension method, and that it isn't part of the IEnumerable interface. An interface is not responsibile for ensuring that extension methods tacked on after its creation work correctly. – Asad Saeeduddin Jun 17 '14 at 19:56
  • @OP It looks like you're not actually using your extension method – Asad Saeeduddin Jun 17 '14 at 20:06
  • @Asad yeah I just saw that... you guys are too fast - give me time to digest :) – Eric Scherrer Jun 17 '14 at 20:07
  • @Eric Try `lst.RepeatIndefinitely().GetEnumerator();` – Asad Saeeduddin Jun 17 '14 at 20:08
  • @JonSkeet, Asad yep that works. Now what, should I just delete the question? – Eric Scherrer Jun 17 '14 at 20:09

2 Answers2

6

It's pretty trivial to create. Iterate and yield the items in a sequence inside of an infinite loop:

public static IEnumerable<T> LoopForever<T>(this IEnumerable<T> source)
{
    while (true)
        foreach (var item in source)
            yield return item;
}
Servy
  • 202,030
  • 26
  • 332
  • 449
0

As Unity3D uses it for concurrent execution (frame updates and coroutines, for instance), try

IEnumerator<T>

http://msdn.microsoft.com/en-us/library/system.collections.ienumerator.aspx

instead of IEnumerable.

dwerner
  • 6,462
  • 4
  • 30
  • 44