Бывают случаи, когда полезно проверить не повторяющийся IEnumerable
, чтобы узнать, пуст ли он. LINQ Any
не подходит для этого, поскольку он потребляет первый элемент последовательности, например
if(input.Any())
{
foreach(int i in input)
{
// Will miss the first element for non-repeatable sequences!
}
}
(Примечание: я знаю, что нет необходимости делать проверку в этом случае - это просто пример! Пример реального мира выполняет Zip
против правого IEnumerable
, который потенциально может быть пусто. Если он пуст, я хочу, чтобы результат был левым IEnumerable
as-is.)
Я придумал потенциальное решение, которое выглядит так:
private static IEnumerable<T> NullifyIfEmptyHelper<T>(IEnumerator<T> e)
{
using(e)
{
do
{
yield return e.Current;
} while (e.MoveNext());
}
}
public static IEnumerable<T> NullifyIfEmpty<T>(this IEnumerable<T> source)
{
IEnumerator<T> e = source.GetEnumerator();
if(e.MoveNext())
{
return NullifyIfEmptyHelper(e);
}
else
{
e.Dispose();
return null;
}
}
Это можно затем использовать следующим образом:
input = input.NullifyIfEmpty();
if(input != null)
{
foreach(int i in input)
{
// Will include the first element.
}
}
У меня есть два вопроса:
1) Это разумная вещь? Возможно, это проблематично с точки зрения производительности? (Я бы предположил, что нет, но стоит спросить.)
2) Есть ли лучший способ достичь той же конечной цели?
ИЗМЕНИТЬ № 1:
Здесь приведен пример не повторяемого IEnumerable
, чтобы уточнить:
private static IEnumerable<int> ReadNumbers()
{
for(;;)
{
int i;
if (int.TryParse(Console.ReadLine(), out i) && i != -1)
{
yield return i;
}
else
{
yield break;
}
}
}
В принципе, все, что происходит от пользовательского ввода или потока и т.д.
ИЗМЕНИТЬ № 2:
Мне нужно уточнить, что я ищу решение, которое сохраняет ленивый характер IEnumerable
- преобразование его в список или массив может быть ответом при определенных обстоятельствах, но это не то, что я после здесь. (Реальная причина в том, что количество элементов в IEnumerable
может быть огромным в моем случае, и важно не хранить их все в памяти сразу.)