Lista<T> o IList<T> [cerrado]

Resuelto Peanut asked hace 15 años • 18 respuestas

¿Alguien puede explicarme por qué querría usar IList en lugar de List en C#?

Pregunta relacionada: ¿Por qué se considera malo exponer?List<T>

Peanut avatar Dec 30 '08 19:12 Peanut
Aceptado

Si está exponiendo su clase a través de una biblioteca que otros usarán, generalmente querrá exponerla a través de interfaces en lugar de implementaciones concretas. Esto le ayudará si decide cambiar la implementación de su clase más adelante para utilizar una clase concreta diferente. En ese caso, los usuarios de su biblioteca no necesitarán actualizar su código ya que la interfaz no cambia.

Si solo lo está usando internamente, es posible que no le importe mucho y List<T>puede que esté bien usarlo.

tvanfosson avatar Dec 30 '2008 12:12 tvanfosson

La respuesta menos popular es que a los programadores les gusta fingir que su software se va a reutilizar en todo el mundo, cuando en realidad la mayoría de los proyectos serán mantenidos por una pequeña cantidad de personas y, por más agradables que sean los fragmentos de sonido relacionados con la interfaz, te estás engañando. tú mismo.

Arquitectura Astronautas . Las posibilidades de que alguna vez escriba su propia IList que agregue algo a las que ya están en el marco .NET son tan remotas que son gelatinas teóricas reservadas para las "mejores prácticas".

astronautas software

Obviamente, si te preguntan cuál usas en una entrevista, dices IList, sonríes y ambos parecen complacidos por ser tan inteligentes. O para una API pública, IList. Ojalá entiendas mi punto.

Arec Barrwin avatar Oct 05 '2009 22:10 Arec Barrwin

La interfaz es una promesa (o un contrato).

Como siempre ocurre con las promesas: cuanto más pequeñas, mejor .

Rinat Abdullin avatar Dec 30 '2008 18:12 Rinat Abdullin

Algunas personas dicen "usar siempre IList<T>en lugar de List<T>".
Quieren que cambies las firmas de tus métodos de void Foo(List<T> input)a void Foo(IList<T> input).

Esta gente está equivocada.

Tiene más matices que eso. Si devuelve un archivo IList<T>como parte de la interfaz pública de su biblioteca, le quedan opciones interesantes para quizás hacer una lista personalizada en el futuro. Puede que nunca necesites esa opción, pero es un argumento. Creo que es el argumento completo para devolver la interfaz en lugar del tipo concreto. Vale la pena mencionarlo, pero en este caso tiene un defecto grave.

Como contraargumento menor, es posible que descubra que cada persona que llama necesita un mensaje List<T>de todos modos y que el código de llamada está plagado de.ToList()

Pero lo que es mucho más importante es que si acepta una IList como parámetro, será mejor que tenga cuidado, porque IList<T>y List<T>no se comportará de la misma manera. A pesar de la similitud de nombre, y pese a compartir interfaz no exponen el mismo contrato .

Supongamos que tiene este método:

public Foo(List<int> a)
{
    a.Add(someNumber);
}

Un colega útil "refactoriza" el método para aceptarlo IList<int>.

Su código ahora está roto porque int[]se implementa IList<int>, pero tiene un tamaño fijo. El contrato para ICollection<T>(la base de IList<T>) requiere que el código que lo utiliza verifique la IsReadOnlybandera antes de intentar agregar o eliminar elementos de la colección. El contrato List<T>no lo hace.

El principio de sustitución de Liskov (simplificado) establece que un tipo derivado debería poder usarse en lugar de un tipo base, sin condiciones previas ni posteriores adicionales.

Esto parece romper el principio de sustitución de Liskov.

 int[] array = new[] {1, 2, 3};
 IList<int> ilist = array;

 ilist.Add(4); // throws System.NotSupportedException
 ilist.Insert(0, 0); // throws System.NotSupportedException
 ilist.Remove(3); // throws System.NotSupportedException
 ilist.RemoveAt(0); // throws System.NotSupportedException

Pero no es así. La respuesta a esto es que el ejemplo usó IList<T>/ICollection<T> incorrectamente. Si utiliza un ICollection<T>, debe verificar el indicador IsReadOnly.

if (!ilist.IsReadOnly)
{
   ilist.Add(4);
   ilist.Insert(0, 0); 
   ilist.Remove(3);
   ilist.RemoveAt(0);
}
else
{
   // what were you planning to do if you were given a read only list anyway?
}

Si alguien le pasa una matriz o una lista, su código funcionará bien si verifica la bandera cada vez y tiene un respaldo... Pero en realidad; ¿quién hace eso? ¿No sabe de antemano si su método necesita una lista que pueda aceptar miembros adicionales? ¿No especificas eso en la firma del método? ¿Qué ibas a hacer exactamente si te pasaran una lista de solo lectura como int[]?

Puedes sustituir a List<T>en el código que use IList<T>/ ICollection<T> correctamente . No puede garantizar que pueda sustituir un código IList<T>/ ICollection<T>into que utilice List<T>.

Hay una apelación al Principio de Responsabilidad Única/Principio de Segregación de Interfaz en muchos de los argumentos para usar abstracciones en lugar de tipos concretos; depende de la interfaz más estrecha posible. En la mayoría de los casos, si está utilizando una interfaz List<T>y cree que podría utilizar una interfaz más estrecha, ¿por qué no IEnumerable<T>? Esto suele ser mejor si no necesita agregar elementos. Si necesita agregar algo a la colección, use el tipo concreto, List<T>.

Para mí IList<T>(y ICollection<T>) es la peor parte del marco .NET. IsReadOnlyviola el principio de mínima sorpresa. Una clase, como Array, que nunca permite agregar, insertar o eliminar elementos, no debería implementar una interfaz con métodos Agregar, Insertar y Quitar. (consulte también https://softwareengineering.stackexchange.com/questions/306105/implementing-an-interface-when-you-dont-need-one-of-the-properties )

¿ Es IList<T>una buena opción para su organización? Si un colega le pide que cambie la firma de un método para usarla IList<T>en lugar de List<T>, pregúntele cómo agregaría un elemento a un archivo IList<T>. Si no lo saben IsReadOnly(y la mayoría de la gente no lo sabe), entonces no lo use IList<T>. Alguna vez.


Tenga en cuenta que el indicador IsReadOnly proviene de ICollection<T> e indica si se pueden agregar o eliminar elementos de la colección; pero para confundir realmente las cosas, no indica si se pueden reemplazar, lo que en el caso de las matrices (que devuelven IsReadOnlys == true) puede ser.

Para obtener más información sobre IsReadOnly, consulte la definición de msdn de ICollection<T>.IsReadOnly

perfectionist avatar Apr 12 '2016 10:04 perfectionist