2011-12-19 22 views
58

En C# utilizo LINQ e IEnumerable un poco. Y todo está bien y bueno (o al menos en su mayor parte).¿Hay un singleton de "lista vacía" en C#?

Sin embargo, en muchos casos me parece que necesito un IEnumerable<X> vacío como valor predeterminado. Es decir, me gustaría

for (var x in xs) { ... } 

para trabajar sin necesidad de una verificación de nulo. Ahora bien, esto es lo que hago actualmente, dependiendo del contexto más amplio:

var xs = f() ?? new X[0];    // when xs is assigned, sometimes 
for (var x in xs ?? new X[0]) { ... } // inline, sometimes 

Ahora, si bien lo anterior es perfectamente bien para mí - es decir, si hay alguna "sobrecarga adicional" con la creación de la matriz objeto que simplemente no les importa - me preguntaba:

¿hay Singleton "IEnumerable inmutable vacío/IList" en C#/.NET.? (Y, incluso si no es así, hay una manera "mejor" para manejar el caso descrito anteriormente?)

Java tiene Collections.EMPTY_LIST inmutable Singleton - "bien escrito" a través de Collections.emptyList<T>() - el cual sirve para este propósito, aunque No estoy seguro si un concepto similar podría funcionar en C# porque los genéricos se manejan de manera diferente.

Gracias.

+0

Bueno, maldición :) Esto es lo que obtengo por enfocarme en List/IList y no Enumerable/IEnumerable, gracias a todos - vota por todas partes. –

+0

http: // stackoverflow.com/questions/3229698/how-can-i-return-an-empty-ienumerable –

+1

'public static class Array {public static readonly T [] Empty = new T [0]; } 'y se puede llamar como:' Array .Empty'. Lo pregunté [aquí en CodeReview] (http://codereview.stackexchange.com/q/20417/17039). –

Respuesta

68

Usted está buscando Enumerable.Empty<int>();

En otras noticias de la lista vacía de Java aspira porque la interfaz Lista expone métodos para añadir elementos a la lista de excepciones que arrojan.

+0

¡Ese es un punto muy válido! Tal vez, ¿merece una nueva pregunta SO? –

+1

Estuviste unos segundos lento y sin enlace de documentación _ * sacudida de dedo * _ ;-) Pero aceptan para expandir el comentario de svicks. –

+0

También los otros muchachos obtuvieron más votos favorables, así que estamos incluso :) Publicaba una pregunta, pero me voy a la cama ahora mismo y no podré seguir con la pregunta. ¿Por qué no publicarlo usted mismo? – Stilgar

17

Creo que estás buscando Enumerable.Empty<T>().

La lista vacía singleton no tiene mucho sentido, porque las listas a menudo son mutables.

10

Creo que la adición de un método de extensión es un lugar limpio gracias alternativas a su capacidad para manejar los nulos - algo así como:

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

    foreach(var x in xs.EmptyIfNull()) 
    { 
    ... 
    } 
1

Microsoft implementó `Cualquier()' como esto (source)

public static bool Any<TSource>(this IEnumerable<TSource> source) 
{ 
    if (source == null) throw new ArgumentNullException("source"); 
    using (IEnumerator<TSource> e = source.GetEnumerator()) 
    { 
     if (e.MoveNext()) return true; 
    } 
    return false; 
} 

Si desea guardar una llamada en la pila de llamadas, en lugar de escribir un método de extensión que llame al !Any(), simplemente reescriba estos tres cambios:

public static bool IsEmpty<TSource>(this IEnumerable<TSource> source) //first change (name) 
{ 
    if (source == null) throw new ArgumentNullException("source"); 
    using (IEnumerator<TSource> e = source.GetEnumerator()) 
    { 
     if (e.MoveNext()) return false; //second change 
    } 
    return true; //third change 
} 
1

El uso de Enumerable.Empty<T>() con listas tiene un inconveniente. Si entrega Enumerable.Empty<T> en el constructor de lista, se asigna una matriz de tamaño 4. Pero si entrega un Collection vacío en el constructor de la lista, no se produce ninguna asignación. Por lo tanto, si usa esta solución en todo su código, lo más probable es que una de las IEnumerable s se use para construir una lista, lo que resultará en asignaciones innecesarias.

Cuestiones relacionadas