Hay momentos en los que es útil comprobar no repetibleIEnumerable
para ver si está vacío o no. El Any
de LINQ no funciona bien para esto, ya que consume el primer elemento de la secuencia, p.Comprobación segura de IEnumerables no repetibles para vacío
if(input.Any())
{
foreach(int i in input)
{
// Will miss the first element for non-repeatable sequences!
}
}
(Nota: Estoy consciente de que no hay necesidad de hacer el registro de entrada en este caso - es sólo un ejemplo El ejemplo del mundo real está realizando una Zip
contra un derecho IEnumerable
que pueden ser potencialmente! . vacía si está vacío, quiero que el resultado sea de la izquierda IEnumerable
tal cual)
yo he llegado con una solución potencial que tiene este aspecto:.
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;
}
}
esto puede entonces ser utilizado de la siguiente manera:
input = input.NullifyIfEmpty();
if(input != null)
{
foreach(int i in input)
{
// Will include the first element.
}
}
Tengo dos preguntas sobre este:
1) ¿Es esta una cosa razonable a hacer? ¿Es probable que sea problemático desde el punto de vista del rendimiento? (Supongo que no, pero vale la pena preguntar.)
2) ¿Hay una mejor manera de lograr el mismo objetivo final?
editar # 1:
Aquí está un ejemplo de un no repetible IEnumerable
, para aclarar:
private static IEnumerable<int> ReadNumbers()
{
for(;;)
{
int i;
if (int.TryParse(Console.ReadLine(), out i) && i != -1)
{
yield return i;
}
else
{
yield break;
}
}
}
Básicamente, las cosas que provienen de entrada de usuario o una corriente, etc.
EDIT # 2:
Tengo que aclarar que estoy buscando una solución que conserva la perezosa naturaleza del IEnumerable
- convirtiéndola en una lista o una matriz puede ser una respuesta en ciertas circunstancias, pero no es lo que estoy buscando aquí. (La razón del mundo real es que el número de elementos en el IEnumerable
puede ser enorme en mi caso, y es importante no almacenarlos todos en la memoria a la vez.)
Eso es un enfoque inteligente. Me interesaría escuchar los comentarios de los demás, pero a mí me parece una forma bastante elegante de resolver su problema. –
No estoy seguro de lo que quiere decir con "no repetible ienumerable". ¿Tienes un ejemplo? El foreach en su primer ejemplo de código no debe perderse el primer elemento, simplemente léalo por segunda vez. No entiendo en qué situación eso no sería posible. –
@ Meta-Knight: He agregado un ejemplo, espero que ayude. –