Бывают случаи, когда полезно проверить неповторяемый IEnumerable
, чтобы узнать, пуст ли он. LINQ Any
не очень хорошо подходит для этого, поскольку он потребляет первый элемент последовательности, например
if(input.Any())
{
foreach(int i in input)
{
// Will miss the first element for non-repeatable sequences!
}
}
(Примечание: я знаю, что в этом случае нет необходимости выполнять проверку - это просто пример! Реальный пример - это выполнение Zip
против правой части IEnumerable
, которая потенциально может быть пустой. Если он пуст, я хочу, чтобы результатом был левый IEnumerable
как есть.)
Я придумал потенциальное решение, которое выглядит так:
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) Есть ли лучший способ достижения той же конечной цели?
EDIT #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;
}
}
}
В основном, вещи, которые поступают из пользовательского ввода или потока, и т.д.
EDIT #2:
Мне нужно уточнить, что я ищу решение, которое сохраняет ленивую природу IEnumerable
- преобразование его в список или массив может быть решением в определенных обстоятельствах, но это не то, что я ищу здесь. (Реальная причина в том, что количество элементов в IEnumerable
в моем случае может быть огромным, и важно не хранить их все в памяти сразу.)