Hal Heinrich
Hal Heinrich

Reputation: 642

How do I bundle existing Reset(), MoveNext(), and Current into a yield-based iterator in C#?

I have a simple class, MyClass, which already has the Reset(), MoveNext(), and Current pieces. But it doesn't provide an iterator, it just exposes those components.

I started with this:

public IEnumerator<MyClass> GetEnumerator()
{
    Reset();
    while (MoveNext())
        yield return Current;
}

Which triggers the following error:

CS1579 foreach statement cannot operate on variables of type 'IEnumerator' because 'IEnumerator' does not contain a public instance definition for 'GetEnumerator'

I tried a bunch of other approaches, but no joy.

Would someone point me in the right direction?

Thanks!

Upvotes: 0

Views: 423

Answers (2)

Bagdan Imr
Bagdan Imr

Reputation: 1286

Key points:

  • You should call foreach on the collection, not on the enumerator
  • Collection itself doesn't need to implement MoveNext and Current, the enumerator does
  • When you implement GetEnumerator() like IEnumerator<T> with yield statements, MoveNext and Current are implemented automatically, parameter type T shouldn't be exactly MyClass

Documentation on CS1579:

To iterate through a collection using the foreach statement, the collection must meet the following requirements:

  • Its type must include a public parameterless GetEnumerator method whose return type is either class, struct, or interface type.
  • The return type of the GetEnumerator method must contain a public property named Current and a public parameterless method named MoveNext whose return type is Boolean.

This is the example of simple collection of numbers from 1 to 5:

class MyCollection
{
    public IEnumerator<int> GetEnumerator()
    {
        for (int index = 1; index <= 5; index++) { 
            yield return index;
        }
    }
}

And now you can iterate through it using foreach:

var collection = new MyCollection();
foreach(var element in collection) {
    Console.Write(element);
}

Upvotes: 0

stephanV
stephanV

Reputation: 183

I'm guessing your code does something like

foreach(var variable in collection.GetEnumerator())
{
 //do some stuff
}

You can leave out the GetEnumerator call. If you class implements IEnumerable it wil be called automatically.

So just:

foreach(var variable in collection)
{
//do some stuff
}

Upvotes: 2

Related Questions