2010-10-08 11 views
29

¿Cuál es la forma estándar de obtener una lista escrita y vacía en C#, o hay una?C#/.NET equivalente para Java Collections. <T> emptyList()?

ETA: Para los que preguntan "¿por qué?": Tengo un método virtual que devuelve un IList (o más bien, post-respuestas, un IEnumerable), y la implementación por defecto está vacía. Lo que devuelva la lista debe ser de solo lectura porque escribirlo sería un error, y si alguien lo intenta, quiero parar y prender fuego inmediatamente, en lugar de esperar a que el error aparezca de una manera sutil más tarde.

+4

¿Qué vas a hacer con una lista de sólo lectura vacía ¿de todas formas? Sólo curioso. – goenning

+0

Supongo que un 'IEnumerable ' vacío es probablemente la respuesta correcta aquí - ¿es realmente necesario un IList ? ¿o solo una colección vacía de solo lectura? –

+1

solo curiosidad, ¿por qué necesita una lista vacía de solo lectura? –

Respuesta

18

personalmente, creo que esto es mejor que cualquiera de las otras respuestas:

static readonly IList<T> EmptyList = new T[0]; 
  • matrices implementan IList<T>.
  • No se puede agregar a una matriz.
  • No se puede asignar a un elemento en una matriz vacía (porque es ninguno).
  • Esto es, en mi opinión, mucho más simple que new List<T>().AsReadOnly().
  • Aún así puede devolver un IList<T> (si lo desea).

Dicho sea de paso, esto es lo que Enumerable.Empty<T>() realmente utiliza bajo el capó, si no recuerdo mal. Entonces teóricamente podrías incluso hacer (IList<T>)Enumerable.Empty<T>() (aunque no veo una buena razón para hacer eso).

+0

Su respuesta realmente solo tiene sentido para mí en términos de los comentarios adjuntos a [la respuesta de Virtlink] (https://stackoverflow.com/a/10659068/712526). – jpaugh

+1

Desde 4.6 ya no necesita proporcionar su propio objeto, simplemente devuelva Array.Empty (). – ZunTzu

21

Usted sólo puede crear una lista:

List<MyType> list = new List<MyType>(); 

Si desea un vacío IEnumerable<T>, utilice Enumerable.Empty<T>():

IEnumerable<MyType> collection = Enumerable.Empty<MyType>(); 

Si realmente quieres un lista de sólo lectura, se podría hacer:

IList<MyType> readonlyList = (new List<MyType>()).AsReadOnly(); 

Esto devuelve un ReadOnlyCollection<T>, que implementa IList<T>.

+2

Pensé esto también, pero luego vi el requisito de solo lectura. Entonces pensé cuál sería el punto de una lista vacía de solo lectura . ¿Qué me estoy perdiendo? –

+0

No hay realmente un 'Solo lista ' ... –

+0

@Jay: Agregué esa opción, también ... –

7
IList<T> list = new List<T>().AsReadOnly(); 

O, si quieres una IEnumerable<>:

IEnumerable<T> sequence = Enumerable.Empty<T>(); 
+1

Desde 4.6, hay una solución mejor: IList list = Array.Empty (); – ZunTzu

-1

¿Qué hay de:

readonly List<T> mylist = new List<T>(); 

No estoy seguro de por qué lo quiere sólo lectura; sin embargo, eso no tiene mucho sentido en la mayoría de los escenarios en los que puedo pensar.

+2

Además, esto no hace que la lista sea de solo lectura. – Timwi

+0

Re: por qué, vea la pregunta editada arriba. –

4

Si desea una lista cuyo contenido no puede ser modificado, que puede hacer:

ReadOnlyCollection<Foo> foos = new List<Foo>().AsReadOnly(); 
2

Para expandir en Dan Tao's answer, la siguiente implementación se puede usar de la misma manera que Enumerable.Empty<T>(), especificando List.Empty<T>() en su lugar.

public static class List 
{ 
    public static IList<T> Empty<T>() 
    { 
     // Note that the static type is only instantiated when 
     // it is needed, and only then is the T[0] object created, once. 
     return EmptyArray<T>.Instance; 
    } 

    private sealed class EmptyArray<T> 
    { 
     public static readonly T[] Instance = new T[0]; 
    } 
} 

Edit: cambiar el código anterior para reflejar el resultado de una discusión con Dan Tao sobre Lazy frente inicialización ansiosos del campo Instance.

+0

¿Inicialización lenta de una matriz de longitud cero? Personalmente creo que es un error, ya que agrega complejidad, empeorará el rendimiento (llamada de método adicional en cada acceso), tiene una condición de carrera (dos hilos que llaman 'List.Empty ()' al mismo tiempo podrían obtener diferentes objetos) y no te compra casi nada (¿cómo crees que el costo de inicialización de un único conjunto de longitud cero se compara con el de JIT compilando una nueva clase?). Vaya con un campo público 'static readonly', ansiosamente inicializado, o, si su conciencia no lo permite, un campo privado más el método' Empty '. ¡Solo mis dos centavos! –

+1

Dos subprocesos obtener diferentes objetos no es un problema. El rendimiento no se ve afectado ya que la llamada es [muy probable que esté en línea] (https://blogs.msdn.com/b/ericgu/archive/2004/01/29/64717.aspx). No veo cómo una línea de lógica real podría agregar severamente a la complejidad. Y por último pero no menos importante: acabo de verificar la implementación de 'Enumerable.Empty ()' y es muy similar a lo que escribí.Si necesita listas vacías de todos los tipos en todo el lugar, use este enfoque ya que guarda las asignaciones y la basura. Si uno solo rara vez necesita una lista vacía, use su 'static readonly'. – Virtlink

+0

Probablemente tengas razón para ponerte a la defensiva, ya que mi comentario ciertamente estaba partiendo los pelos. Sin embargo, diferentes objetos podrían ser un problema si, por ejemplo, tuvieras algún código crítico que dependiera de la comprobación 'if (list == List.Empty ())'. Además, ¿cómo ahorra este enfoque en las asignaciones y la basura? –

6

A partir de .NET 4.6 también se puede utilizar:

IList<T> emptyList = Array.Empty<T>(); 

Esto no sólo para crear una nueva instancia de una vez por cada tipo diferente que especifique como T.

+0

Al igual que String.Empty, que también siempre hace referencia a la misma instancia en lugar de crear una nueva cadena vacía. –

+0

@David De Sloovere el literal de cadena vacía "" también hace referencia a la misma instancia gracias al interrogatorio de cadena (solo para lectores que se sentirían obligados a reemplazar "" por String.Empty). – ZunTzu

Cuestiones relacionadas