How to implement the correct IEnumerator interface for multiple foreach?

I have code like:

class T : IEnumerable, IEnumerator { private int position = -1; public T() { } public IEnumerator GetEnumerator() { return this; } public object Current { get { return position; } } public bool MoveNext() { position++; return (position < 5); } public void Reset() { position = -1; } } //Using in code: T t = new T(); foreach (int i in t) //to do something 

Everything works fine in the code above, but when I use the following:

 foreach (int i in t) if (i == 2) foreach (int p in t) //print p else //print i 

It prints (in parentheses the second loop): 0 1 (3 4) 2 instead of 0 1 (0 1 2 3 4) 2 3 4 I tested it on the list and collection, and they do it right. How can I achieve what I need?

+4
source share
2 answers

You cannot, because you made your code surface a single enumerator, the IMO error itself. The best version for me:

 class T : IEnumerable<int> { public IEnumerator<int> GetEnumerator() { int i = 0; while(i < 5) { yield return i; i++; } } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } 

The compiler will create the correct devices to achieve this using separate counters.

If you are not writing for .NET 1.1, then if you find that you are writing the enumarator manually, there is a very good chance that you can do this with difficulty, and you are mistaken as a bonus.

If you really must do this hard:

 class T : IEnumerable<int> { public T() { } public IEnumerator<int> GetEnumerator() { return new TEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } private class TEnumerator : IEnumerator<int> { private int position = -1; public int Current { get { return position; } } object IEnumerator.Current { get { return Current; } } void IDisposable.Dispose() {} public bool MoveNext() { position++; return (position < 5); } public void Reset() { position = -1; } } } 

The value here is that different instances of TEnumerator allow you to iterate the same T separately.

+9
source
 foreach (int i in t) if (i == 2) foreach (int p in t) //print p else //print i 

Always use curly braces first, while you back off what happens, the other if there will be confusing things.

 foreach (int i in t) { if (i == 2) { foreach (int p in t) { //print p } } else { //print i } } 

But the problem: you only have one counter for the T instance, and you are using the same instance. Therefore, you do it once. If you want to allow parallel enumerations, the enumerator object must be shared with GetEnumerator , which returns a new instance each time.

+5
source

All Articles