2008-09-22 10 views
9

Estoy tratando de encontrar el fragmento de código más reutilizable, pero elegante, posible para determinar si un IEnumerable. En el ideal, esta debería ser una función a la que pueda llamar absolutamente en cualquier momento que necesite saber si un IEnumerable está vacío.¿Qué es una pieza de código sólida, elegante y reutilizable para determinar si un IEnumerable está vacío en .NET?

Si bien he desarrollado una respuesta para .NET 3.5 que me ha funcionado hasta ahora, mi pensamiento actual es que no hay una respuesta perfecta, ya que un IEnumerable puede encapsular técnicamente una colección (o cola de iteradores) que modifica los resultados subyacentes a medida que se repiten, lo que causaría problemas. Sin embargo, esto también sería un impedimento para implementar IEnumerable.Count(), y eso no impidió que MS lo proporcionara.

Así que pensé que lo pondría en SO para ver si alguien tiene uno mejor, y en caso de que alguien más lo encuentre útil.

Edit: Wow, no puedo creer que no supiera sobre IEnumerable.Any. Sabía que existía, pero nunca me molesté en comprobar qué hacía. Deja que esto sea una lección. Lee la documentación. El hecho de que un nombre de método no implique que hace lo que quiere, no significa que no hace lo que usted quiere.

Respuesta

22
!enumerable.Any() 

Intentará capturar el primer elemento solamente.

Para ampliar cómo y por qué funciona esto, cualquiera determina si alguno de los componentes de un IEnumerable coincide con una función dada, si no se proporciona ninguno, entonces cualquier componente tendrá éxito, lo que significa que la función devolverá verdadero si existe un elemento el enumerable.

+0

Wow .... No puedo creer que no sabía acerca de esto. ¡Gracias! –

+2

Es nuevo en .Net 3.5 – Keith

2

para .NET 1/2:

IEnumerator e; 
try 
{ 
    e = enumerable.GetEnumerator(); 
    return e.MoveNext(); 
} 
finally 
{ 
    if (e is IDisposable) 
     e.Dispose(); 
} 

O, con los genéricos:

using (IEnumerator<T> e = enumerable.GetEnumerator()) 
{ 
    return e.MoveNext(); 
} 
0

Una cosa a tener cuidado de con cualquiera de estos métodos es que no todas las enumeraciones pueden ser arrollado de vuelta, por ejemplo, todas las implementaciones de System.Data.IDataReader solo pueden ejecutarse una vez.

En estos casos, realmente no tiene un costo en un bucle foreach, siempre y cuando tenga en cuenta que puede que ni siquiera se repita una vez.

2

Tienes razón en que no hay una respuesta perfecta. IEnumerable solo es compatible con la iteración y no garantiza que la enumeración sea repetible. No puede averiguar si una enumeración contiene elementos sin llamar a MoveNext al menos una vez, y una vez que lo haya hecho no puede garantizar que pueda reutilizar la enumeración: se permite que IEnumerable.Reset arroje una excepción NotSupportedException. De http://msdn.microsoft.com/en-us/library/system.collections.ienumerator.reset.aspx:

"El método Restablecer se proporciona para la interoperabilidad COM. No necesariamente debe implementarse, en cambio, el implementador puede simplemente lanzar una NotSupportedException".

Los métodos de extensión como IEnumerable <T> .Count y IEnumerable <T> .Any necesitan llamar a MoveNext bajo las sábanas. Envolturas útiles, pero no evite el hecho de que en los casos (raros) en que una enumeración no es compatible con Restablecer, podría tener un problema.

+0

Entendido, pero creo que cualquier código que opere en instancias de IEnumerable en formas distintas a agregar más iteradores en la cola (retorno de rendimiento) tendrá este riesgo. –

Cuestiones relacionadas