[c#] Lista <T> o IList <T>



Answers

La respuesta menos popular es que a los programadores les gusta pretender que su software va a ser reutilizado en todo el mundo, cuando de hecho la mayoría de los proyectos serán mantenidos por una pequeña cantidad de gente y sin importar cuán buenas sean las relacionadas con la interfaz, estás engañando tú mismo.

Astronautas de arquitectura . Las posibilidades de que alguna vez escriba su propio IList que agregue algo a las que ya están en .NET Framework son tan remotas que es teóricamente jelly tots reservado para las "mejores prácticas".

Obviamente, si te preguntan cuál usas en una entrevista, dices IList, sonríe, y ambos se ven complacidos por ser tan listos. O para una API pública, IList. Espero que entiendas mi punto.

Question

¿Alguien puede explicarme por qué me gustaría usar IList sobre List en C #?

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




Lo haría porque la definición de IList o ICollection se abriría para otras implementaciones de sus interfaces.

Es posible que desee tener un IOrderRepository que defina una colección de pedidos en un IList o ICollection. A continuación, podría tener diferentes tipos de implementaciones para proporcionar una lista de pedidos siempre que se ajusten a las "reglas" definidas por su IList o ICollection.




IList <> casi siempre es preferible según el consejo del otro anunciante, sin embargo, tenga en cuenta que hay un error en .NET 3.5 sp 1 cuando ejecuta un IList <> a través de más de un ciclo de serialización / deserialización con el WCF DataContractSerializer.

Ahora hay un SP para solucionar este error: KB 971030




El caso más importante para usar interfaces sobre implementaciones está en los parámetros de su API. Si su API toma un parámetro List, entonces cualquier persona que lo use debe usar List. Si el tipo de parámetro es IList, la persona que llama tiene mucha más libertad y puede usar clases de las que nunca escuchó, que tal vez ni siquiera existieron cuando se escribió su código.




Un principio de TDD y OOP generalmente es la programación de una interfaz, no una implementación.

En este caso específico, ya que esencialmente está hablando de un constructo de lenguaje, no uno personalizado, generalmente no importará, pero supongamos, por ejemplo, que encontró que List no admitía algo que necesitaba. Si hubiera utilizado IList en el resto de la aplicación, podría extender List con su propia clase personalizada y aún así poder pasarla sin refactorizar.

El costo de hacer esto es mínimo, ¿por qué no ahorrarse el dolor de cabeza más tarde? De eso se trata el principio de la interfaz.




Normalmente, un buen enfoque es usar IList en su API pública (cuando corresponda, y se necesita una semántica de lista), y luego enumerar internamente para implementar la API. Esto le permite cambiar a una implementación diferente de IList sin romper el código que usa su clase.

La lista de nombres de clase puede cambiarse en el siguiente .NET framework, pero la interfaz nunca cambiará ya que la interfaz está contratada.

Tenga en cuenta que, si su API solo se va a usar en bucles foreach, etc., entonces quizás desee considerar exponer IEnumerable en su lugar.




Me gustaría dar vuelta la pregunta un poco, en lugar de justificar por qué debería utilizar la interfaz sobre la implementación concreta, tratar de justificar por qué usaría la implementación concreta en lugar de la interfaz. Si no puede justificarlo, use la interfaz.




List<T> es una implementación específica de IList<T> , que es un contenedor que se puede direccionar de la misma manera que una matriz lineal T[] utilizando un índice entero. Cuando especifica IList<T> como el tipo del argumento del método, solo especifica que necesita ciertas capacidades del contenedor.

Por ejemplo, la especificación de la interfaz no aplica una estructura de datos específica para ser utilizada. La implementación de List<T> ocurre con el mismo rendimiento para acceder, eliminar y agregar elementos como una matriz lineal. Sin embargo, podría imaginarse una implementación respaldada por una lista vinculada, para la cual agregar elementos al final es más barato (tiempo constante) pero el acceso aleatorio es mucho más costoso. (Tenga en cuenta que .NET LinkedList<T> no implementa IList<T> .)

Este ejemplo también le indica que puede haber situaciones en las que necesite especificar la implementación, no la interfaz, en la lista de argumentos: en este ejemplo, siempre que requiera una característica de rendimiento de acceso particular. Esto generalmente se garantiza para una implementación específica de un contenedor ( List<T> documentación: "Implementa la interfaz genérica IList<T> usando una matriz cuyo tamaño se incrementa dinámicamente según sea necesario.").

Además, es posible que desee considerar exponer la menor funcionalidad que necesita. Por ejemplo. si no necesita cambiar el contenido de la lista, probablemente debería considerar usar IEnumerable<T> , que IList<T> extiende.




¿Qué pasa si .NET 5.0 reemplaza System.Collections.Generic.List<T> a System.Collection.Generics.LinearList<T> . .NET siempre posee el nombre List<T> pero garantizan que IList<T> es un contrato. Así que en mi humilde opinión (al menos yo) no se supone que use el nombre de alguien (aunque es .NET en este caso) y nos metamos en problemas más adelante.

En caso de utilizar IList<T> , la persona que llama siempre se asegura de que las cosas funcionen, y el implementador puede cambiar la colección subyacente a cualquier implementación concreta alternativa de IList




Related