Iterator без yield

Как решить проблему с бесконечной итерацией, чтобы выводилось 0,2,4,6,8.Без yield и коллекций?

    public class MyIterator<T> : IEnumerator<T>, IEnumerable<T>
    {
        public Func<int, bool> Predicate;

        public IEnumerator<T> enumerator;
        public MyIterator(IEnumerator<T> enumer, Func<int, bool> predicate)
        {
            Predicate = predicate;
            enumerator = enumer;

        }
        public T Current => enumerator.Current;
        object IEnumerator.Current => enumerator.Current;
        void IDisposable.Dispose()
        {
           
        }
        public int Index { get; private set; }
        public int Count { get; private set; }
// Custom movenext
        public bool MoveNext()
        {
            if (Predicate(Index))
            {
                Console.WriteLine(Index);
                Index++;
                return true;
            }
            Index++;
            return false;
        }
        void IEnumerator.Reset()
        {
           
        }
        public IEnumerator<T> GetEnumerator()
        {
            return enumerator;
        }
        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }
public static class Program
{
    public static Func<int, bool> Predicate;

    public static MyIterator<int> enumer;
    public static IEnumerable<int> GetEnumaration()
    {
        int i = 0;
        while (true)
        {
            yield return i++;
        }
    }

    public static MyIterator<int> MyWhere(this IEnumerable<int> enumerator, Func<int, bool> predicate)
    {
        Predicate = predicate;
        enumer = new MyIterator<int>(enumerator.GetEnumerator(), predicate);
        return enumer; 
    }

    public static IEnumerable<int> MyTake(this MyIterator<int> enumer, int count)
    {
        var en = enumer.GetEnumerator();

       int cnt = 0;

        while (cnt <= count)
        {
            if(en.MoveNext())
            {
                cnt++;
            }
        }

        return GetEnumaration();
    }

    public static void Main()
    {

        foreach (var item in GetEnumaration().MyWhere(x => x % 2 == 0).MyTake(5))
        {
            Console.WriteLine(item);
        }
        Console.ReadLine();
    }
}

Ответы (1 шт):

Автор решения: aepot

Да вроде ничего сложного не должно быть, типичная реализация шаблона проектирования "Конечный автомат".

class MyEnumerable : IEnumerable<int>
{
    public IEnumerator<int> GetEnumerator() => new MyIterator();

    IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}

class MyIterator : IEnumerator<int>
{
    private int _current;
    private int _state;
    public int Current => _current;
    object IEnumerator.Current => Current;

    public bool MoveNext()
    {
        switch (_state)
        {
            case 0:
                _current = 0;
                _state = 1;
                break;
            case 1:
                _current += 2;
                break;
        }
        return true;
    }

    public void Reset()
    {
        _state = 0;
    }

    public void Dispose()
    {
    }
}
static void Main(string[] args)
{
    Console.WriteLine(string.Join(",", new MyEnumerable().Take(5)));
}
0,2,4,6,8

То же самое, только с заданием начального значения и функции с помощью делегата.

class MyEnumerable : IEnumerable<int>
{
    private readonly int _start;
    private readonly Func<int, int> _func;

    public MyEnumerable(int start, Func<int, int> func)
    {
        _start = start;
        _func = func;
    }

    public IEnumerator<int> GetEnumerator() => new MyIterator(_start, _func);

    IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}

class MyIterator : IEnumerator<int>
{
    private int _current;
    private int _state;
    private readonly int _start;
    private readonly Func<int, int> _func;
    public int Current => _current;
    object IEnumerator.Current => Current;

    public MyIterator(int start, Func<int, int> func)
    {
        _start = start;
        _current = start;
        _func = func;
    }

    public bool MoveNext()
    {
        switch (_state) 
        {
            case 0: 
                _current = _start;
                _state = 1;
                break;
            case 1:
                _current = _func(_current);
                break;
        }
        return true;
    }

    public void Reset()
    {
        _state = 0;
    }

    public void Dispose()
    {
    }
}
static void Main(string[] args)
{
    Console.WriteLine(string.Join(",", new MyEnumerable(0, i => i + 2).Take(5)));
}

Вывод такой же.


Что касается расширений, далеко ходить не надо, вот шпаргалка

→ Ссылка