2011-11-09 19 views
8

Si deseo realizar acciones tales como .Where (...) o .Max (...), debo asegurarme de que la lista no sea nula y tenga un recuento superior a cero. Además de hacer algo como lo siguiente cada vez que quiero usar la lista:¿Mejor manera de verificar si hay elementos en la lista?

if(mylist != null && mylist.Count > 0) 
{...} 

hay algo más en línea o lambda como técnica que puedo usar? ¿O alguna otra técnica más comprimida?

+5

En mi humilde opinión, los objetos como una lista nunca deben ser nulos. Siempre los inicializo si son miembros de la clase, y si se devuelven desde una función de mi propia creación, me aseguro de que la función devuelva una lista vacía en lugar de nula. –

+0

Posible duplicado de la respuesta en: http://stackoverflow.com/questions/41319/checking-if-a-list-is-empty-with-linq – VS1

+0

Siempre puede escribir sus propios métodos de extensión para usar las acciones tales como Where() o Max() que incluiría su prueba nula y Count antes de usar el método de extensión real. – Paul

Respuesta

3

Mi preferencia general es tener instancias de lista vacías, en lugar de variables de lista nulos. Sin embargo, no todos pueden engatusar a sus compañeros de trabajo en este arreglo. Puede protegerse de variables de lista nula usando este método de extensión.

public static IEnumerable<T> EmptyIfNull<T>(this IEnumerable<T> source) 
{ 
    return source ?? Enumerable.Empty<T>(); 
} 

Llamado por:

Customers result = myList.EmptyIfNull().Where(c => c.Name == "Bob"); 

mayoría de los métodos de LINQ trabajan en colecciones vacías. Dos métodos que no son Min y Max. En general, llamo a estos métodos contra un IGrouping. La mayoría de las implementaciones de IGrouping tienen al menos un elemento (por ejemplo, IGups generado por GroupBy o ToLookup). Para otros casos, puede usar Enumerable.DefaultIfEmpty.

int result = myList.EmptyIfNull().Select(c => c.FavoriteNumber).DefaultIfEmpty().Max(); 
1

Puede intentar myList.Any() en lugar de , pero aún deberá comprobar null.

+0

Correcto, por lo que aún debe verificar si no tiene nulo. – Igor

2

No permita que la lista sea nula

Asegúrese de que el objeto está siempre en un estado válido. Al asegurarse de que la lista nunca sea nula, nunca debe verificar que la lista sea nula.

public class MyClass 
{ 
    private readonly IEnumerable<int> ints; 

    public MyClass(IEnumerable<int> ints) 
    { 
     this.ints = ints; 
    } 

    public IEnumerable<int> IntsGreaterThan5() 
    { 
     return this.ints.Where(x => x > 5); 
    } 
} 

Aunque esta lista estaban vacías, todavía se obtendría una vuelta válida IEnumerable<int>.

Max y Min sobrecargas mediante los tipos anulables

Eso todavía no resuelve el problema "min" "Max" y sin embargo. Hay una sobrecarga de Max y Min que toman selectores. Esos sobrecargas selectores pueden volver enteros con valores nulos, por lo que su método se convierte en máximo esto:

this.ints.Max(x => new int?(x)); 

Por lo tanto, se corre Max y comprobar para ver si usted ha conseguido un valor nulo o un número entero de vuelta. voila!

Otras Opciones

métodos de extensión personalizada

También puede escribir sus propios métodos de extensión.

public static MinMaxHelper() 
{ 
    public static int? MaxOrDefault(IEnumerable<int> ints) 
    { 
     if(!ints.Any()) 
     { 
      return null; 
     } 

     return ints.Max(); 
    } 

    public static int MaxOrDefault(IEnumerable<int> ints, int defaultValue) 
    { 
     if(!ints.Any()) 
     { 
      return defaultValue; 
     } 

     return ints.Max(); 
    } 
} 

Sustitución de métodos de extensión LINQ

Y por último, recordar que la estructura en métodos de extensión LINQ se puede anular con sus propios métodos de extensión con las firmas correspondientes. Por lo tanto, podría escribir un método de extensión para reemplazar .Where (...) y .Max (...) para devolver nulo (o un valor predeterminado) en lugar de arrojar una ArgumentNullException si el Enumerable es nulo.

+2

¿Estás respondiendo esta pregunta? – Snowbear

+0

Lo siento, debo haber tenido un mal día. He visto una gran cantidad de comprobación nula y la creación de instancias de la lista dentro de ciclos while y tal últimamente, en lugar de solo crear una instancia de la lista con la clase. –

1

Si existe el riesgo de que su lista sea nula, siempre tendrá que comprobarlo antes de llamar a cualquiera de sus métodos, pero podría utilizar el método Any() en lugar de contar. Esto volverá a ser cierto tan pronto como cuente un elemento, independientemente de si hay uno o más elementos en la lista. Esto ahorra iteración a lo largo de toda la lista, que es lo que va a hacer conde:

if(mylist != null && mylist.Any()) 
{...} 
9
public static class LinqExtensions 
{ 
    public static bool IsNullOrEmpty<T>(this IEnumerable<T> items) 
    { 
      return items == null || !items.Any(); 
    } 
} 

entonces usted puede hacer algo como

if (!myList.IsNullOrEmpty()) 
.... 
+0

Lo que hace esta condición '! Items.Any(); ¿? – sll

+0

@sll, no, Any() lanzará una ArgumentNullException si la fuente es nula. –

+1

nunca se ejecutará porque antes 'items == null' comprueba ... – sll

2

Uso empty colecciones en lugar de null colecciones.Where funcionará perfectamente contra una colección vacía, por lo que no es necesario que se asegure de que Count > 0 antes de llamarlo. También puede llamar al Max en una colección vacía si primero hace un bit of gymnastics.

Para IEnumerable<T> uso Enumerable.Empty<T>()

Para T[] uso new T[0]

Para List<T> uso new List<T>()

1

Puede utilizar ?? operador que convierte nula al valor que usted suministra en el lado derecho:

public ProcessList(IEnumerable<int> ints) 
{ 
    this.ints = ints ?? new List<int>(); 
} 

Por cierto: No es un problema para procesar una lista vacía utilizando LINQ.

1

No necesita marcar Count para llamar al Where. Max necesita una lista no vacía de los tipos de valor pero que se puede superar con un reparto en línea, por ejemplo

int? max = new List<int>().Max(i => (int?)i); // max = null 
Cuestiones relacionadas