Почему вы хотите написать класс итератора? Весь смысл блока итератора в том, что вам не нужно ...
т.е.
public IEnumerator<T> GetEnumerator() {
int position = 0; // state
while(whatever) {
position++;
yield return ...something...;
}
}
Если вы добавите больше контекста (например, почему вышеупомянутое не может работать), мы, вероятно, можем помочь больше.
Но, если возможно, избегайте написания класса итератора. Они много работают, и их легко ошибиться.
Кстати, вам не нужно беспокоиться о Reset
- он в значительной степени устарел и его никогда не следует использовать (поскольку на него нельзя полагаться для работы с произвольным перечислителем). 1011 *
Если вы хотите использовать внутренний итератор, это тоже хорошо:
int position = 0;
foreach(var item in source) {
position++;
yield return position;
}
или если у вас есть только перечислитель:
while(iter.MoveNext()) {
position++;
yield return iter.Current;
}
Вы можете также рассмотреть возможность добавления состояния (в виде кортежа) к тому, что вы получаете:
class MyState<T> {
public int Position {get;private set;}
public T Current {get;private set;}
public MyState(int position, T current) {...} // assign
}
...
yield return new MyState<Foo>(position, item);
Наконец, вы можете использовать подход расширения / делегирования в стиле LINQ с Action<int,T>
для предоставления позиции и значения вызывающей стороне:
static void Main() {
var values = new[] { "a", "b", "c" };
values.ForEach((pos, s) => Console.WriteLine("{0}: {1}", pos, s));
}
static void ForEach<T>(
this IEnumerable<T> source,
Action<int, T> action) {
if (source == null) throw new ArgumentNullException("source");
if (action == null) throw new ArgumentNullException("action");
int position = 0;
foreach (T item in source) {
action(position++, item);
}
}
Выходы:
0: a
1: b
2: c