Erik Funkenbusch
Erik Funkenbusch

Reputation: 93444

How to refactor usage of an iterator

I have some code i'd like to refactor that uses a C# iterator (ie IEnumerable). Unfortunately, I can't see to quite figure out the best way to allow other functions to work with the iterator without causing it to restart the iterator.

For example:

NewLineEnumerator nle = new NewLineEnumerator();

while (bytesRead > 0)
{
  var nlenum = nle.Process(inputData, bytesRead);
  foreach (string block in nlenum)
  {
    DoSomething(nlenum);
  }
}

void DoSomething(IEnumerable<string> myiter)
{
  foreach (var s in myiter)
  {
     // myiter is restarted, and begins at the start of the iterator again
  }
}

You might be asking why i would want to do this. The reason is that I have a stream of data, surrounded by "command blocks". Depending on the command, I send it to a different subfunction to process. So I want to keep iterating where i left off in the stream either at the start, or at the end.

Any suggestions here?

Upvotes: 0

Views: 188

Answers (2)

Bradley Grainger
Bradley Grainger

Reputation: 28207

As Nick said, create one IEnumerator<string> and pass it between methods. The code would look something like:

NewLineEnumerator nle = new NewLineEnumerator();

while (bytesRead > 0)
{
    var nlenum = nle.Process(inputData, bytesRead);
    using (var enumerator = nlenum.GetEnumerator())
    {
        while (enumerator.MoveNext())
        {
            DoSomething(enumerator);
            Console.WriteLine(enumerator.Current);
        }
    }

    // ensure that bytesRead is decremented by the code that runs above
}

void DoSomething(IEnumerator<string> myenum)
{
    while (myenum.MoveNext())
    {
        if (ShouldProcess(myenum.Current))
        {
            // process it
        }
        else
        {
            // return to outer loop
            break;
        }
    }
}

(Note that if you're using .NET 1.0, and IEnumerable, not IEnumerable<string>, the using statement may not compile.)

Upvotes: 2

Nick Gunn
Nick Gunn

Reputation: 724

Pass an IEnumerator<string> rather than the IEnumerable<string>, by calling GetEnumerator(). It will retain the state across calls.

Upvotes: 5

Related Questions