Sé que IList es la interfaz y List es el tipo concreto, pero todavía no sé cuándo usar cada una. Lo que estoy haciendo ahora es que si no necesito los métodos Ordenar o Buscar todos, uso la interfaz. Estoy en lo cierto? ¿Hay una mejor manera de decidir cuándo usar la interfaz o el tipo concreto?
180
Respuestas:
Hay dos reglas que sigo:
Entonces, al escribir una función o método que tome una colección, escríbala no para tomar una Lista, sino una IList <T>, una ICollection <T> o IEnumerable <T>. Las interfaces genéricas seguirán funcionando incluso para listas heterogéneas porque System.Object también puede ser una T. Hacer esto le ahorrará dolor de cabeza si decide usar una Pila o alguna otra estructura de datos más adelante. Si todo lo que necesita hacer en la función es foreach a través de ella, IEnumerable <T> es realmente todo lo que debe pedir.
Por otro lado, cuando devuelve un objeto fuera de una función, desea darle al usuario el conjunto de operaciones más rico posible sin que tenga que usarlo. Entonces, en ese caso, si se trata de una Lista <T> internamente, devuelva una copia como Lista <T>.
fuente
if...else
cadena con lais
palabra clave para calcular encuentra un tipo mucho más rico y termina lanzándolo y usándolo de todos modos. Por lo tanto, no necesariamente se garantiza que oculte nada mediante el uso de una interfaz básica, en lugar de simplemente ocultarlo. Sin embargo, hacerlo más difícil también puede hacer que el escritor del código consumidor piense dos veces acerca de cómo lo están usando.Add()
yRemove()
pueden tener efectos más allá de la colección. Devolver una interfaz de solo lectura comoIEnumerable
suele ser el camino a seguir para los métodos de recuperación de datos. Su consumidor puede proyectarlo en un tipo más rico según sea necesario.Las pautas de Microsoft verificadas por FxCop desalientan el uso de List <T> en API públicas; prefiera IList <T>.
Por cierto, ahora casi siempre declaro las matrices unidimensionales como IList <T>, lo que significa que puedo usar constantemente la propiedad IList <T> .Count en lugar de Array.Length. Por ejemplo:
fuente
Hay algo importante que la gente siempre parece pasar por alto:
Puede pasar una matriz simple a algo que acepte un
IList<T>
parámetro, y luego puede llamarIList.Add()
y recibirá una excepción de tiempo de ejecución:Unhandled Exception: System.NotSupportedException: Collection was of a fixed size.
Por ejemplo, considere el siguiente código:
Si llama a eso de la siguiente manera, obtendrá una excepción de tiempo de ejecución:
Esto sucede porque el uso de matrices simples con
IList<T>
viola el principio de sustitución de Liskov.Por esta razón, si llama
IList<T>.Add()
, puede considerar solicitar un enList<T>
lugar de unIList<T>
.fuente
List<T>
másIList<T>
, también debe ser consciente de las razones por las queIList<T>
se recomienda. (Por ejemplo, blogs.msdn.microsoft.com/kcwalina/2005/09/26/… )IList<T>.Add()
. No estoy diciendo que no debas usarIList<T>
, solo estoy señalando una posible trampa. (Que tienden a utilizarIEnumerable<T>
oIReadOnlyList<T>
oIReadOnlyCollection<T>
con preferencia aIList<T>
si puedo.)Estoy de acuerdo con el consejo de Lee para tomar parámetros, pero no regresar.
Si especifica sus métodos para devolver una interfaz, eso significa que puede cambiar la implementación exacta más adelante sin que el método de consumo lo sepa. Pensé que nunca necesitaría cambiar de una Lista <T>, pero luego tuve que cambiar para usar una biblioteca de listas personalizada para la funcionalidad adicional que proporcionaba. Como solo había devuelto una IList <T>, ninguna de las personas que usaban la biblioteca tuvo que cambiar su código.
Por supuesto, eso solo necesita aplicarse a métodos que son visibles externamente (es decir, métodos públicos). Personalmente uso interfaces incluso en el código interno, pero como puede cambiar todo el código usted mismo si realiza cambios importantes, no es estrictamente necesario.
fuente
IEnumerable
Debe intentar usar el tipo menos específico que se adapte a su propósito.
IEnumerable
es menos específico queIList
.Se usa
IEnumerable
cuando desea recorrer los elementos de una colección.IList
IList
implementosIEnumerable
.Debe usar
IList
cuando necesite acceso por índice a su colección, agregar y eliminar elementos, etc.Lista de
List
implementosIList
.fuente
Siempre es mejor usar el tipo base más bajo posible. Esto le da al implementador de su interfaz, o al consumidor de su método, la oportunidad de usar lo que quiera detrás de escena.
Para las colecciones, debe intentar utilizar IEnumerable siempre que sea posible. Esto brinda la mayor flexibilidad pero no siempre es adecuado.
fuente
ToList()
devuelvan su devoluciónIEnumerable<T>
que ya era una lista y devuelva unaIList<T>
. Ahora, los clientes pueden beneficiarse de lo que puede proporcionar sin esfuerzo.Si está trabajando dentro de un único método (o incluso en una sola clase o ensamblaje en algunos casos) y nadie afuera verá lo que está haciendo, use la totalidad de una Lista. Pero si está interactuando con código externo, como cuando devuelve una lista de un método, entonces solo desea declarar la interfaz sin necesariamente vincularse a una implementación específica, especialmente si no tiene control sobre quién compila contra su código después. Si comenzó con un tipo concreto y decidió cambiar a otro, incluso si usa la misma interfaz, va a romper el código de otra persona a menos que comience con una interfaz o un tipo base abstracto.
fuente
No creo que haya reglas duras y rápidas para este tipo de cosas, pero generalmente sigo las pautas de usar la forma más ligera posible hasta que sea absolutamente necesario.
Por ejemplo, supongamos que tiene una
Person
clase y unaGroup
clase. UnaGroup
instancia tiene muchas personas, por lo que una Lista aquí tendría sentido. Cuando declare el objeto de la lista, usaréGroup
unIList<Person>
y lo instanciaré como aList
.Y, si ni siquiera necesita todo
IList
, siempre puede usarloIEnumerable
también. Con los compiladores y procesadores modernos, no creo que haya realmente ninguna diferencia de velocidad, por lo que esto es más una cuestión de estilo.fuente
Con mayor frecuencia, es mejor utilizar el tipo utilizable más general, en este caso, la IList o incluso mejor la interfaz IEnumerable, para que pueda cambiar la implementación convenientemente más adelante.
Sin embargo, en .NET 2.0, hay una cosa molesta: IList no tiene un método Sort () . En su lugar, puede usar un adaptador suministrado:
fuente
Debe usar la interfaz solo si la necesita, por ejemplo, si su lista se convierte en una implementación de IList que no sea List. Esto es cierto cuando, por ejemplo, usa NHibernate, que convierte ILists en un objeto de bolsa NHibernate al recuperar datos.
Si List es la única implementación que usará para una determinada colección, no dude en declararla como una implementación concreta de List.
fuente
En situaciones en las que me encuentro, rara vez uso IList directamente.
Por lo general, solo lo uso como argumento para un método
Esto me permitirá hacer un procesamiento genérico en casi cualquier matriz en .NET Framework, a menos que use IEnumerable y no IList, lo que sucede a veces.
Realmente se reduce al tipo de funcionalidad que necesita. Sugeriría usar la clase List en la mayoría de los casos. IList es mejor para cuando necesita hacer una matriz personalizada que podría tener algunas reglas muy específicas que le gustaría encapsular dentro de una colección para que no se repita, pero todavía quiere que .NET la reconozca como una lista.
fuente
El objeto AList le permite crear una lista, agregarle cosas, eliminarla, actualizarla, indexarla, etc. La lista se usa siempre que solo desee una lista genérica donde especifique el tipo de objeto y eso es todo.
IList por otro lado es una interfaz. Básicamente, si desea crear su propio tipo de Lista, digamos una clase de lista llamada BookList, entonces puede usar la Interfaz para darle métodos básicos y estructura a su nueva clase. IList es para cuando desea crear su propia subclase especial que implementa List.
Otra diferencia es: IList es una interfaz y no se puede instanciar. La lista es una clase y se puede instanciar. Significa:
fuente