2010-03-13 11 views

Respuesta

17

Tenga en cuenta que List<> es una implementación de IList<> con almacenamiento real, es decir, contiene una matriz en segundo plano. En general, un IList<> puede ser un proxy para otra cosa. En db4o y linq a sql, su IList<> podría 'apuntar a una consulta', es decir, acceder a la lista activará una operación de base de datos.

De esta manera, puede realizar myList.Skip(600).Take(20); para realizar la paginación y solo en este paso se ejecutará la consulta real. Un List<> que contiene un millón de entradas será enorme, mientras que puede haber IList<> s que tienen un enorme Count, pero no consumen una cantidad significativa de memoria, siempre y cuando no accedan a los elementos.

ConvertAll requerirá que todos y cada uno de los objetos sean instanciados por lo que es una operación costosa. Por lo tanto, es mejor hacer explícita la operación y obligarlo a recuperar una implementación específica de la interfaz. Obviamente, la conversión requiere la instancia de todos los objetos de todos modos, por lo que no hay beneficio en hacerlo de forma perezosa.

+0

contento de saber sobre el caso db4o, lo estoy usando ahora mismo. para el caso db4o, no debería cerrar el db antes de usar el IList <> ¿correcto? – Benny

+0

Así es, terminarás con una 'DatabaseClosedException' luego. – mnemosyn

+1

Skip y Take son métodos IEnumerable <>, no necesariamente IList <>. – Dykam

4

Porque la interfaz define un solo comportamiento, mientras que una clase puede implementar varias interfaces diferentes y también tiene características no especificadas por una interfaz.

Si desea las capacidades de la clase List<T>, no utilice una referencia IList<T>. Use una referencia List<T> desde el principio.

11

¿Por qué no utilizar IEnumerable<T>.Select en lugar de List<T>.ConvertAll? Desde IList hereda IEnumerable. Vea esto question en SO.

1

La interfaz IList está diseñada para implementarse en todas partes. Al omitir los métodos de conveniencia, eso significa menos trabajo para implementar la interfaz y menos oportunidades para escribir errores.

Afortunadamente, LINQ acelera esto y agrega un montón de métodos útiles a través de la función "método de extensión". Select y Cast son particularmente útiles para fines de conversión. Asegúrese de orientar .NET Framework 3.5, hacer referencia al ensamblaje System.Core y tener un using System.Linq; para verlo.

2

Simplemente porque IList(T) es una interfaz, mientras que List(T) es una de varias clases en el bcl .NET que implementa IList(T) para el propósito de tener funcionalidad indizador. No todas las clases que implementan IList(T) requerirán un método ConvertAll(), que se usa para convertir una lista genérica de un cierto tipo genérico en otro.

0

Cada método o definición de propiedad dentro de una interfaz obliga a cada implementación de la interfaz a proporcionar código para ello. Si una interfaz es implementada por diez mil clases en todo el mundo, agregando a la interfaz un método que solo tomaría una línea de código ejecutable para implementar aumentaría por lo menos cuarenta mil líneas la cantidad total de código necesario para todas esas implementaciones (asumiendo el blanco normal -sucesiones de convenciones). Por el contrario, agregar un método de ayuda a una clase no impone requisitos en las interfaces que lo implementan.

Dicho sea de paso, uno de mis principales artículos de la lista de deseos para .net sería un medio por el cual una interfaz podría declarar que los miembros tienen una implementación predeterminada a través de un método estático (p.IFoo que incluye el miembro string Boz(int param) podría especificar que si el código para una clase que intenta implementar IFoo no incluye ese miembro, el compilador o el tiempo de ejecución deben generar automáticamente el método string IFoo.Boz(int param) { return IFoo_Helpers.Boz(this, param);}. Si tal recurso de método existiera en .net desde la versión 2.0, podría haber ahorrado cientos de miles, si no millones, de líneas de código por ahora, con solo IEnumerable<T> incluir una implementación predeterminada IEnumerator IEnumerable.GetEnumerator() {return IEnumerable_Helpers<T>.GetEnumerator(this);}, con el último método simplemente siendo static IEnumerable GetEnumerator(IEnumerable<T> it) {return it.GetEnumerator();} . Tal característica habría permitido a las interfaces ofrecer muchas más características a sus consumidores sin imponer más trabajo en sus implementadores. Además, a diferencia de los métodos de extensión que deben estar vinculados estáticamente en el sitio de llamada, dichos métodos de interfaz se vincularán en la implementación, permitiendo así que las anulaciones específicas de la implementación se usen cuando corresponda (por ejemplo, si IEnumerable<T> ofreció un método ToList, List<T> podría define una implementación rápida que crea un nuevo List<T> preinicializado al tamaño adecuado y usa Array.Copy para poblarlo, y las implementaciones de IEnumerable<T> que devolverían secuencias interminables podrían arrojar una excepción (en lugar de engullir toda la memoria que podrían obtener), pero la mayoría de las implementaciones no tendrían que hacer nada con ese método; simplemente podrían diferir a la función de ayuda predeterminada para propósitos generales que enumeraría los elementos en un nuevo List<T> y lo dejaría crecer según fuera necesario.

Cuestiones relacionadas