Implementing IEnumerable on an Enumerator?

G

Gordon Rundle

It drives me nuts that I can't use foreach with an enumerator
instance. I would like the following to be functionally identical:
foreach (Object o in MyCollection) ...
foreach (Object o in MyCollection.GetEnumerator()) ...

For enumerable types that are under my control, is there any reason
not to create an enumerator type that itself implements IEnumerable?
Like so:

class MyEnumerator : IEnumerable, IEnumerator {
private IEnumerator mEnumerator = null;
public MyEnumerator(IEnumerator e) { mEnumerator = e; }
public MyEnumerator(IEnumerable e) { mEnumerator =
e.GetEnumerator(); }
public object Current { get { return mEnumerator.Current; } }
public void Reset() { mEnumerator.Reset(); }
public bool MoveNext() { return mEnumerator.MoveNext(); }
public IEnumerator GetEnumerator() { return this; }
}


I understand that using the foreach construct, Dispose() will be
called on the enumerator at the end of the loop, if it's defined; what
are the implications for a wrapper class like this? Are there other
possible issues I should be aware of?

thanks,
G. Rundle
 
M

Mickey Williams

Gordon Rundle said:
It drives me nuts that I can't use foreach with an enumerator
instance. I would like the following to be functionally identical:
foreach (Object o in MyCollection) ...
foreach (Object o in MyCollection.GetEnumerator()) ...

The reason is that enumerators are stateful and after the foreach statement
are fully consumed. A type that implements IEnumerable can dispense endless
enumerators.
I understand that using the foreach construct, Dispose() will be
called on the enumerator at the end of the loop, if it's defined; what
are the implications for a wrapper class like this? Are there other
possible issues I should be aware of?

If the enumerator implements IDisposable it will be disposed. If it doesn't,
it won't.
 
M

Mickey Williams

The reason is that enumerators are stateful and after the foreach statement
are fully consumed. A type that implements IEnumerable can dispense endless
enumerators.

An example may be clearer:

If you allowed enumerators in foreach, this code would probably not work as
expected:

LoanEnumerator loans = borrower.Loans;
foreach(Loan loan in loans)
PrintLoan(loan);
// loans enumerator instance already consumed at this point
foreach(Loan loan in loans)
RecordLoan(loan);
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top