Search code examples
c#yieldyield-keyword

C# yield Follow-up to the end


If I call methodA and then methodB output is: "121234". But I need output: "1234", "12" from methodA and "34" from methodB. I need to remember where getNumber ended with the return, and the next call continue from here. It is possible?

MethodA snipset

int x = 0;
foreach (var num in GetNumber())
{
    if (x == 2)
    {
        break;
    }
    x++;
    Console.Write(num);
}

MethodB snipset

int x = 0;
foreach (var num in GetNumber())
{
    if (x == 4)
    {
        break;
    }
    x++;
    Console.Write(num);
}

GetNumber

static IEnumerable<int> GetNumber()
{
    int x = 0;
    while (true)
    {
        yield return x++;
    }
}

Solution

  • You can initialize x outside the method:

    static class InfiniteContinuingSequence
    {
        static int x = 0;
    
        public static IEnumerable<int> GetNumbers()
        {
            while (true)
            {
                yield return x++;
            }
        }
    }
    

    But you will have to explicitly be careful when and where this sequence gets enumerated. If it is inadvertently enumerated multiple times, you will "lose" numbers in the sequence; if you try to exhaustively enumerate GetNumbers() you'll get either an infinite loop or an overflow; and if you try to call this from multiple threads without locking, you'll get potentially odd behavior.


    Instead, I might suggest to either use an explicit enumerator, or be able to specify a "restart point" to your method (in this case at least you will not get odd behavior by multiple enumerations):

    static IEnumerable<int> GetNumbers(int startingPoint = 0)
    {
        int x = startingPoint;
        while (true)
        {
            yield return x++;
        }
    }