He estado jugando con C # para Windows y el desarrollo de ASP.net MVC desde hace algún tiempo. Pero todavía no estoy claro en algunas áreas. Estoy tratando de entender la diferencia básica y los problemas de rendimiento con el uso e intercambio de tipos similares de interfaces de colección genéricas .
¿Cuál es la diferencia básica entre IEnumerable<T>
, ICollection<T>
, List<T>(Class)
?
Parece que los uso e intercambio sin ver ningún problema en mis aplicaciones. Además, ¿hay más colecciones genéricas similares como estas que puedan intercambiarse con esas tres?
c#
generics
interfaces
Pankaj Upadhyay
fuente
fuente
Respuestas:
List <T> es una clase e implementa las interfaces ICollection <T> e IEnumerable <T> . Además, ICollection <T> extiende la interfaz IEnumerable <T>. No son intercambiables, al menos no desde todos los puntos de vista.
Si tiene una Lista <T>, tiene la garantía de que este objeto implementa métodos y propiedades que la interfaz ICollection <T> y IEnumerable <T> deben implementar. El compilador lo sabe y se le permite convertirlos "abajo" a una ICollection <T> o IEnumerable <T> implícitamente. Sin embargo, si tiene una ICollection <T>, primero debe verificar explícitamente en su código si es una Lista <T> o alguna otra cosa, tal vez un Diccionario <T> (donde T es un KeyValuePair ) antes de convertirlo en lo que deseo.
Usted sabe que ICollection extiende IEnumerable, por lo que puede convertirlo en IEnumerable. Pero si solo tiene un IEnumerable, nuevamente no se le garantiza que sea una Lista. Puede ser, pero podría ser otra cosa. Debería esperar una excepción de conversión no válida si intenta emitir una Lista <T> a un Diccionario <T>, por ejemplo.
Por lo tanto, no son "intercambiables".
Además, hay muchas interfaces genéricas, consulte lo que puede encontrar en el espacio de nombres System.Collections.Generic .
Editar: con respecto a su comentario, no hay absolutamente ninguna penalización de rendimiento si usa List <T> o una de las interfaces que implementa. Aún necesitará crear un nuevo objeto, consulte el siguiente código:
list , myColl y myEnum apuntan al mismo objeto. Ya sea que lo declare como una Lista o una ICollection o un IEnumerable, todavía necesito que el programa cree una Lista. Podría haber escrito esto:
myColl , en tiempo de ejecución sigue siendo una lista.
Sin embargo , este es el punto más importante ... para reducir el acoplamiento y aumentar la capacidad de mantenimiento , siempre debe declarar sus variables y parámetros de método utilizando el mínimo denominador posible para usted, ya sea una interfaz o una clase abstracta o concreta.
Imagine que lo único que necesita el método "PerformOperation" es enumerar elementos, hacer un trabajo y salir, en ese caso no necesita los cien métodos más disponibles en la Lista <T>, solo necesita lo que está disponible en IEnumerable <T >, por lo que debería aplicarse lo siguiente:
Al hacerlo, usted y otros desarrolladores saben que cualquier objeto de una clase que implemente la interfaz IEnumerable <T> se puede asignar a este método. Puede ser una Lista, un Diccionario o una clase de colección personalizada que otro desarrollador haya escrito.
Si, por el contrario, especifica que necesita explícitamente una Lista concreta <T> (y aunque rara vez es el caso en la vida real, aún puede suceder), usted y otros desarrolladores saben que debe ser una Lista u otra clase concreta heredada de la lista.
fuente
IList
lugar deList
en la declaración del método.List<>
una funcionalidad específica, como.AddRange()
. ElIList<>
no expone eso.Eche un vistazo a las páginas de MSDN para ICollection e IEnumerable .
En términos muy abstractos, así es como concibo estos tipos.
Un IEnumerable es cualquier cosa que se pueda enumerar, es decir, iterar. No necesariamente significa una 'colección'; por ejemplo, un IQueryable implementa IEnumerable y no es una colección, pero es algo que se puede consultar para devolver objetos. Para implementar IEnumerable, un objeto solo necesita poder devolver un objeto cuando se lo consulta. Podría decir que tengo una Enumerable de tareas que voy a hacer hoy (no es una lista porque no la he escrito o formulado, pero podría decirte lo que voy a hacer ahora, y si preguntaras 'y luego', podría decirte la siguiente tarea).
Una ICollection es más concreta que una IEnumerable. Una diferencia clave es que una Colección sabe cuántos elementos contiene; para calcular cuántos elementos hay en un Enumerable, puede recorrerlos y contarlos de manera efectiva:
Una colección es típicamente algo que ya sabe dónde están todos sus elementos, y no tendrá que ir a buscarlos o generarlos cuando los solicite. Es más ... concreto que un Enumerable.
En mi opinión, la diferencia entre un Enumerable y una Colección es mucho mayor que la diferencia entre una Colección y una Lista. De hecho, me cuesta pensar en una diferencia práctica entre una Colección y una Lista, pero creo que Lista proporciona mejores métodos para buscar y ordenar.
Otros tipos de colección incluyen
Queue
yStack
, así comoDictionary
.Los nombres de estos tipos son bastante útiles: puede concebir una cola y una pila como sus contrapartes del mundo real, y considerar las diferencias que podría tener con una Lista.
fuente
List
es unaICollection
, pero unaICollection
no siempre es unaList
(Queue
,Stack
,Dictionary
, ...)Queue<int> queue = (Queue<int>)list;
arrojará unInvalidCastException
cuandolist
no es unQueue<int>
. La diferencia entre la cola y la lista está fuera del alcance de esta pregunta.IQueryable:
la consulta no se ejecuta hasta que realmente se repite sobre los elementos, tal vez haciendo un .ToList ()
IEnumerable:
lista de artículos solo hacia adelante. No puede llegar al "elemento 4" sin pasar los elementos 0-3. lista de solo lectura, no puede agregarla ni eliminarla. Todavía podría usar la ejecución diferida.
IList:
el acceso aleatorio a la lista completa en su totalidad en la memoria admite agregar y quitar
ICollection:
Está entre IEnumerable e IList. Lo que es "mejor" depende de sus requisitos. Por lo general, aunque un IEnumerable es "suficientemente bueno" si solo desea mostrar elementos. Al menos siempre use la variante genérica.
fuente