При реализации соственных методов MyWhere и MyTake не работает с условием while(true), работает только если ставить ограничение в цикл
//Доработать пример , реализовав собственные экстеншен методы MyWhere и MyTake. При реализации нельзя использовать yiled и коллекции. Только кастомные итераторы.
public static IEnumerable<int> GetEnumaration()
{
int i = 0;
while (true)
{
yield return i++;
}
}
public static IEnumerable<int> MyWhere(this IEnumerable<int> enumerator, Func<int, bool> predicate)
{
// return enumerator.Where(predicate);
int[] array = enumerator.ToArray();
int whereSize = 0;
for (int i = 0; i < array.Length; i++)
{
if (predicate(array[i]))
{
whereSize++;
}
}
int[] result = new int[whereSize];
int j = 0;
for (int i = 0; i < array.Length; i++)
{
if (predicate(array[i]))
{
result[j] = array[i];
j++;
}
}
return result.AsEnumerable();
}
public static IEnumerable<int> MyTake(this IEnumerable<int> enumerator, int count)
{
// return enumerator.Take(count);
int[] array = enumerator.ToArray();
int[] result = new int[count];
for (int i = 0; i < count; i++)
{
result[i] = array[i];
}
return result.AsEnumerable();
}
public static void Main()
{
foreach (var item in GetEnumaration().Where(x => x % 2 == 0).Take(5))
{
Console.WriteLine(item);
}
Console.WriteLine("------------");
foreach (var item in GetEnumaration().MyWhere(x => x % 2 == 0).MyTake(5))
{
Console.WriteLine(item);
}
Console.ReadLine();
}
Ответы (1 шт):
Вы упускаете смысл ленивых операций. А смысл их в том, чтобы проходить только по той части перечисления, что интересна конечному юзеру.
Вот как пример, ваш бесконечный цикл. Я добавил вывод в консоль, чтобы было понятно что происходит
public static IEnumerable<int> GetEnumaration()
{
int i = 0;
while (true)
{
Console.WriteLine($"GetEnumaration - {i}");
yield return i++;
}
}
А теперь полгядим на MyWhere - это операция фильтрации и она будет применяться также лениво
public static IEnumerable<int> MyWhere(this IEnumerable<int> source, Predicate<int> predicate)
{
foreach (var item in source)
{
if (predicate(item)) yield return item;
}
}
Для MyTake все тоже просто - мы проходим только по нужным нам элементам. То есть нет разона читать 100 элементов из перечисления, если нам надо только 3
public static IEnumerable<int> MyTake(this IEnumerable<int> source, int count)
{
if (count != 0)
{
int cnt = 0;
foreach (var item in source)
{
yield return item;
cnt++;
if (cnt >= count) break;
}
}
}
Проверка будет простой
foreach (var item in GetEnumaration().MyWhere(x => x % 3 == 0).MyTake(3))
{
Console.WriteLine(item);
}
Вывод
GetEnumaration - 0
0
GetEnumaration - 1
GetEnumaration - 2
GetEnumaration - 3
3
GetEnumaration - 4
GetEnumaration - 5
GetEnumaration - 6
6
Как видите, мы читали только те элементы из бесконечного цикла, которые нам интересны и не более.
Ваш же вызов .ToArray() пытается читать всю последовательность до конца, а у неё нет конца, там же while(true) стоит. Мой пример читает только до того момента, пока ему следует читать - как только порция нужных данных получена, больше ничего читать не надо из бесконечной последовательности.