Joel Coehoorn
Joel Coehoorn

Reputation: 415840

Infinite IEnumerable in a foreach loop

After answering this question I put together the following C# code just for fun:

public static IEnumerable<int> FibonacciTo(int max)
{     
    int m1 = 0;
    int m2 = 1;
    int r = 1;

    while (r <= max)
    {
       yield return r;

       r = m1 + m2;
       m1 = m2;
       m2 = r;
    }
}

foreach (int i in FibonacciTo(56).Where(n => n >= 24) )
{
   Console.WriteLine(i);
}

The problem is that I don't like needing to pass a max parameter to the function. Right now, if I don't use one the code will output the correct data but then appear to hang as the IEnumerable continues to work. How can I write this so that I could just use it like this:

foreach (int i in Fibonacci().Where(n => n >= 24 && n <= 56) )
{
   Console.WriteLine(i);
}

Upvotes: 5

Views: 883

Answers (2)

Jon Skeet
Jon Skeet

Reputation: 1500775

You need to use a combination of SkipWhile and TakeWhile instead.

foreach (int i in Fibonacci().SkipWhile(n => n < 24)
                             .TakeWhile(n => n <= 56))
{
   Console.WriteLine(i);
}

These are able to end loops depending on a condition; Where streams its input (filtering appropriately) until the input runs out (in your case, never).

Upvotes: 12

John Downey
John Downey

Reputation: 14114

I don't think this is possible unless you write your own LINQ provider. In the example you gave you are using LINQ to Objects which will need to completely evaluate the IEnumerable before it can apply a filter to it.

Upvotes: -2

Related Questions