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)));
}
Вывод такой же.
Что касается расширений, далеко ходить не надо, вот шпаргалка