C# yield Follow-up to the end

147 views Asked by At

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

There are 2 answers

0
lc. On BEST ANSWER

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++;
    }
}
0
Richard Schneider On

Change GetNumber to

static int x = 0;

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

The issue is that you have two enumerations of GetNumber. By making x static you will get the results you want. But beware this is not thread safe code.