Ручной перечислитель в C#
Интерфейсы IEnumerable<T> и IEnumerator<T>
задают обход коллекции: первый возвращает перечислитель,
второй - шаги MoveNext и текущий элемент.
Порядок можно описать отдельным классом перечислителя без
yield return: состояние хранится в полях, а
MoveNext сдвигает позицию.
Последовательность целых от 1 до 3 отдаёт отдельный класс перечислителя, без yield return.
До первого MoveNext позиция стоит перед первым числом, поэтому каждый успешный шаг отдаёт следующее.
Reset здесь не поддерживается: для нового прохода нужен новый перечислитель:
using System.Collections;
foreach (int x in new Counter(1, 3))
{
Console.WriteLine(x); // выведет 1, 2, 3
}
class Counter : IEnumerable<int>
{
private readonly int _from;
private readonly int _to;
public Counter(int from, int to) => (_from, _to) = (from, to);
public IEnumerator<int> GetEnumerator() =>
new CounterEnumerator(_from, _to);
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
class CounterEnumerator : IEnumerator<int>
{
private readonly int _to;
private int _current;
private int _pos;
public CounterEnumerator(int from, int to)
{
_to = to;
_current = from - 1;
_pos = from - 1;
}
public int Current => _current;
object IEnumerator.Current => Current;
public bool MoveNext()
{
if (_pos >= _to) return false;
_pos++;
_current = _pos;
return true;
}
public void Reset() => throw new NotSupportedException();
public void Dispose() { }
}
Сделайте перечислитель для кодов 10 и 20 и выведите каждый код на отдельной строке.