2009-04-19 22 views

risposta

80

IEnumerable fornisce solo funzionalità "iterable" minime. Puoi attraversare la sequenza, ma questo è tutto. Ciò ha degli svantaggi: ad esempio, è molto inefficiente contare gli elementi usando IEnumerable, o ottenere l'ennesimo elemento - ma ha anche dei vantaggi - per esempio, un oggetto IEnumerable potrebbe essere una sequenza infinita, come la sequenza di numeri primi.

L'array è una raccolta di dimensioni fisse con accesso casuale (ad esempio, è possibile indicizzarvi).

L'elenco è una raccolta di dimensioni variabili (ad esempio, è possibile aggiungere e rimuovere elementi) con accesso casuale.

IList è un'interfaccia che astrae funzionalità di elenco (contare, aggiungere, rimuovere, accesso indicizzatore) di distanza dalle varie classi concrete, come List, BindingList, ObservableCollection, ecc

+2

In base alla risposta accettata qui http://stackoverflow.com/questions/1826658/what-is-faster-or-preferred-ienumerable-toarray-or-tolist. Contare su IEnumerable è quasi lo stesso perché tenta di chiamare Count su ICollection – Karsten

+12

Sì e no. Il metodo di estensione Count() verifica se l'IEnumerable è anche un ICollection e chiama la sua proprietà Count se lo è. Se IEnumerable * non è * un ICollection, Count() torna a ripetere la sequenza. Forse avrei dovuto dire "è molto inefficiente contare gli elementi usando * only * IEnumerable", perché ovviamente la presenza di IEnumerable non impedisce di usare un metodo più efficiente se l'oggetto ne ha uno, e il LINQ ai metodi di estensione degli oggetti fai esattamente questo. – itowlson

9

IEnumerable e IList sono interfaces. Array e List sono classi. Array implementa IEnumerable. List implementa IList che estende IEnumerable.

Modifica: come accennato in un commento, Array implementa anche IList.

+4

Array implementa anche IList. – itowlson

+0

Neanche io! Cosa succede se si inizia a chiamare IList.RemoveAt su un array, comunque? –

+0

Genera una NotSupportedException. (Nota IList.RemoveAt e metodi IList simili sono esplicitamente implementati su Array in modo che non vengano visualizzati su un normale riferimento Array!) – itowlson

13

IEnumerable è un'interfaccia che consente l'iterazione attraverso una raccolta di elementi (ad esempio tramite la parola chiave foreach).

Un array è un .NET intrinseco. Tiene oggetti dello stesso tipo, ma ha una dimensione fissa. Una volta creato un array con elementi x, non può crescere o restringersi.

IList definisce l'interfaccia per un elenco e implementa anche IEnumerable.

Elenco implementa l'interfaccia IList; è un tipo concreto di lista.

La differenza tra elenchi .NET e array è che le liste possono avere elementi aggiunti a loro - crescono per essere abbastanza grandi da contenere tutti gli elementi richiesti. L'elenco lo memorizza internamente in un array e, quando l'array non è più abbastanza grande da contenere tutti gli elementi, viene creato un nuovo array e gli elementi vengono copiati.

Gli array IList & implementano entrambi IEnumerable. Ecco come funzionano le interfacce: le classi implementano il contratto e si comportano in modo simile e possono essere trattate allo stesso modo di conseguenza (sapete che la classe implementa IEnumerable, non è necessario conoscere i come oi perché). Ti suggerisco di leggere le interfacce e così via.

+1

Aggiunta di questo commento per i lettori che non leggono tutte le risposte: array ed Elenco <> implementano IList <> (gli array implementano molto di esplicitamente, presumibilmente perché molti membri lanciano NotSupportedException). È anche più corretto dire che IList eredita da IEnumerable piuttosto che dire che lo implementa. – phoog

2

IEnumerable è un'interfaccia general-purpose che è utilizzato da molte classi, come ad esempio Array, List e String per consentire a qualcuno di eseguire un'iterazione su una raccolta. Fondamentalmente, è ciò che guida l'istruzione foreach.

IList indica in genere come esporre le variabili di tipo List agli utenti finali. Questa interfaccia consente l'accesso casuale alla raccolta sottostante.

6

La generazione di una raccolta IEnumerable è pigra. Esempio:

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

Nel metodo Qualcosa la chiamata a GetTwoInts() non sarà effettivamente causare i GetTwoInts metodo in corso di esecuzione in quanto l'enumerazione non è mai iterato sopra.

+0

Potresti elaborarlo un po '? Non sono sicuro di aver capito bene. Puoi mostrare una riga di codice più tardi in base alla quale verrà effettivamente eseguito quel metodo? Grazie! – paaone

+0

@paaone metti 'twoInts' in un' foreach' o chiama 'twoInts.ToList()'. – row1

0

Questo è un vecchio post, ma ho ancora pensato di rispondere. IEnumerable è un comportamento mentre Array è una struttura di dati (insieme contiguo di elementi con dimensione fissa, che facilita l'accesso agli elementi per indici). Quando una matrice implementa IEnumerable, si suppone che mostri anche la proprietà intrinseca di IEnumerable (che facilita l'iterazione sulla raccolta).

0

per integrare le altre risposte, notare che c'è una differenza tra il prestazioniIList<T> e List<T> durante l'esecuzione di un'istruzione foreach.

Questo perché l'oggetto iteratore restituito da List<T>.GetEnumerator è un valore di tipo mentre quello restituito da IList<T>.GetEnumerator è un riferimento di tipo, e richiede quindi un'allocazione di memoria (vedi Enumerator of value type of list in c#).

A mio parere, IList<T> non è comunque un'ottima interfaccia. Ad esempio chiamando Add può lanciare (vedi Why array implements IList?). Se hai bisogno di incapsulamento staresti meglio usando IEnumerable<T> o IReadOnlyList<T>.

Problemi correlati