2009-04-19 13 views

Respuesta

80

IEnumerable proporciona solo una funcionalidad mínima "iterable". Puedes recorrer la secuencia, pero eso es todo. Esto tiene desventajas, por ejemplo, es muy ineficiente contar elementos usando IEnumerable, o para obtener el enésimo elemento, pero también tiene ventajas, por ejemplo, un IEnumerable podría ser una secuencia sin fin, como la secuencia de números primos.

La matriz es una colección de tamaño fijo con acceso aleatorio (es decir, puede indexarla).

La lista es una colección de tamaño variable (es decir, puede agregar y eliminar elementos) con acceso aleatorio.

IList es una interfaz que abstrae la funcionalidad de listas (contar, añadir, eliminar el acceso indexador) de distancia de las diversas clases concretas, tales como la lista, BindingList, ObservableCollection, etc.

+2

De acuerdo con la respuesta aceptada aquí http://stackoverflow.com/questions/1826658/what-is-faster-or-preferred-ienumerable-toarray-or-tolist. Contar con IEnumerable es casi lo mismo porque intenta invocar Contar en ICollection – Karsten

+12

Sí y no. El método de extensión Count() comprueba si IEnumerable también es una colección IC y llama a su propiedad Count si es así. Si IEnumerable * no es * una ICollection, Count() vuelve a iterar la secuencia. Tal vez debería haber dicho "es muy ineficiente contar los elementos usando * solo * IEnumerable" porque, por supuesto, la presencia de IEnumerable no te detiene usando un método más eficiente si el objeto tiene uno, y los métodos de extensión LINQ to Objects haz exactamente eso. – itowlson

9

IEnumerable y IList son interfaces. Array y List son clases. Array implementa IEnumerable. List implementa IList que extiende IEnumerable.

Editar: como itowlson se menciona en un comentario, Array también implementa IList.

+4

Array también implementa IList. – itowlson

+0

¡Tampoco yo! Sin embargo, ¿qué sucede si comienzas a llamar a IList.RemoveAt en una matriz? –

+0

Lanza una NotSupportedException. (Nota: IList.RemoveAt y métodos IList similares se implementan explícitamente en Array para que no aparezcan en una referencia normal de Array.) – itowlson

13

IEnumerable es una interfaz que permite la iteración a través de una colección de elementos (por ejemplo, a través de la palabra clave foreach).

Una matriz es .NET intrínseca. Tiene elementos del mismo tipo, pero tiene un tamaño fijo. Una vez que crea una matriz con x elementos, no puede crecer ni reducirse.

IList define la interfaz para una lista y también implementa IEnumerable.

La lista implementa la interfaz IList; es un tipo concreto de lista.

La diferencia entre las listas .NET y las matrices es que las listas pueden tener elementos agregados: crecen lo suficiente como para contener todos los elementos necesarios. La lista almacena esto internamente en una matriz y, cuando la matriz ya no es lo suficientemente grande como para contener todos los elementos, se crea una nueva matriz y se copian los elementos.

IList & las matrices implementan IEnumerable. Así es como funcionan las interfaces: las clases implementan el contrato y se comportan de manera similar y pueden ser tratadas de manera similar como resultado (usted sabe que la clase implementa IEnumerable, no necesita saber cómo o por qué). Te sugiero que leas las interfaces y demás.

+1

Agregando este comentario para los lectores que no leen todas las respuestas: arrays y List <> ambos implementan IList <> (las matrices implementan gran parte de explícitamente, presumiblemente porque muchos de los miembros lanzan una NotSupportedException). También es más correcto decir que IList hereda de IEnumerable que decir que lo implementa. – phoog

2

IEnumerable es una interfaz de uso general que es utilizado por muchas clases, como Array, List y String para permitir que alguien itere sobre una colección. Básicamente, es lo que impulsa la declaración foreach.

IList es generalmente cómo expone las variables del tipo List a los usuarios finales. Esta interfaz permite el acceso aleatorio a la colección subyacente.

6

La generación de una colección de IEnumerable es floja. Ejemplo:

public IEnumerable<int> GetTwoInts() 
{ 
    yield return 1; 
    yield return 2; 
} 
public void Something() 
{ 
    var twoInts = GetTwoInts(); 
} 

En el Algo método de la llamada a GetTwoInts() en realidad no resultará en los GetTwoInts método se ejecuta desde la enumeración no se itera sobre.

+0

¿Podría por favor elaborarlo un poco? No estoy seguro si entendí bien. ¿Puedes mostrar una línea de código más adelante que en realidad resultará en que se ejecute ese método? Gracias! – paaone

+0

@paaone puso 'twoInts' en un' foreach' o call 'twoInts.ToList()'. – row1

0

Esta es una publicación anterior, pero todavía se pensó en responder. IEnumerable es un comportamiento mientras Array es una estructura de datos (colección contigua de elementos con tamaño fijo, lo que facilita el acceso a elementos por índices). Cuando una matriz implementa IEnumerable, se supone que también representa la propiedad inherente de IEnumerable (de facilitar la iteración sobre la colección).

0

Para complementar las otras respuestas, tenga en cuenta que hay una diferencia entre rendimientoIList<T> y List<T> al ejecutar una instrucción foreach.

Eso es porque el objeto iterador devuelto por List<T>.GetEnumerator es un tipo de valor mientras que el devuelto por IList<T>.GetEnumerator es un tipo de referencia, y por lo tanto requiere una asignación de memoria (ver Enumerator of value type of list in c#).

En mi opinión, IList<T> no es una muy buena interfaz de todos modos. Por ejemplo, puede lanzar Add (ver Why array implements IList?). Si necesita encapsulamiento, sería mejor usar IEnumerable<T> o IReadOnlyList<T>.

Cuestiones relacionadas