2012-05-02 12 views
32

Ho una domanda sull'ordinazione in IEnumerable (o IEnumerable<T>, non importa).IEnumerable and order

Come sappiamo, scorrendo IEnumerable è pseudo-codice può essere scritto nel modo seguente:

while (enumerable.HasNext()) 
{ 
    object obj = enumerable.Current; 
    ... 
} 

Ora, assumere, che si ha la necessità di operare su un ordinato raccolta. È possibile utilizzare IEnumerable in questo caso o è meglio provare altri metodi (ad esempio IList) con supporto per l'indicizzazione?

In altre parole: si fa il contratto di IEnumerable assumersi alcuna responsabilità circa l'ordine in generale?

UPD: Quindi, IEnumerable non è una media adeguata per un'interfaccia generica che garantisce l'ordine. La nuova domanda è quale interfaccia o classe dovrebbe essere utilizzata per una collezione immutabile con ordine?? ReadonlyCollection? IList? Entrambi contengono il metodo Add() (anche se non è implementato in quello precedente). Qualche suggerimento?

P.S I miei pensieri: IEnumerable non fornisce alcuna garanzia circa l'ordinamento. La corretta attuazione potrebbe tornare stessi elementi in ordine differente in differenti enumerazioni (considerare una query SQL)

P.P.S. Sono a conoscenza di LINQ First(), ma se IEnumerable non dice una parola riguardo al suo ordinamento, questa estensione è piuttosto inutile.

risposta

25

IEnumerable/IEnumerable<T> non fornisce garanzie sull'ordinazione, ma le implementazioni che utilizzano IEnumerable/IEnumerable<T> potrebbero o meno garantire l'ordine.

Per esempio, se si enumerano List<T>, l'ordine è garantito, ma se si enumerano HashSet<T> non viene fornito tale garanzia, ma entrambi saranno enumerati utilizzando l'interfaccia IEnumerable<T>.

+1

Un altro esempio è 'Dizionario <,>'. È chiaramente documentato che l'ordine in cui sono enumerate le sue voci non è definito. Quindi codice come 'dict.Last(). Key' (dove' dict' è un 'Dictionary <,>' e 'Last()' è il metodo di estensione LINQ) non ha senso. (Ho sentito che uno sviluppatore ha fatto esattamente questo). –

+1

Aggiungo che ho già detto che è importante capire correttamente le garanzie sull'ordine per alcune raccolte generiche. Quindi la garanzia dell'ordine non riguarda un particolare ordine (per esempio, come risultato dell'ordinamento), ma garantisce che l'ordine degli elementi della stessa collezione sia lo stesso per le successive enumerazioni. La maggior parte delle collezioni non lo garantisce esplicitamente. IList rappresenta solo un tipo di dizionario in cui le chiavi sono indici. –

+0

IOrderedEnumerable può essere un segno per credere che la raccolta garantisce l'ordine (sebbene l'interfaccia non sia ancora), ma è più del necessario - di solito rappresenta un particolare ordine SORT, mentre abbiamo bisogno di QUALSIASI ordine (casuale) che sia solo garantito tra le numerazioni. Per concludere, solo l'implementazione concreta può davvero garantire l'ordine (ad esempio Array, List ). –

12

Dettaglio di implementazione. IEnumerable enumera l'oggetto: il modo in cui viene implementato dipende dall'implementazione. La maggior parte degli elenchi, ecc., Scorre lungo il loro ordine naturale (indice 0 verso l'alto ecc.).

il contratto di IEnumerable ci garantisce un ordine in generale?

No, garantisce solo l'enumerazione (ogni articolo una volta ecc.). IEnumerable non ha un ordine garantito perché è utilizzabile anche su articoli non ordinati.

so su LINQ First(), ma se IEnumerable non dice una parola su di esso è ordine, questa estensione è piuttosto inutile.

No, non lo è, perché potresti avere un ordine intrinseco. Si fornisce SQL come esempio: il risultato è un oggetto IEnumerable, ma se si dispone di un ordine forzato prima (utilizzando OrderBy()), l'oggetto IEnumerable viene ordinato per definizione di LINQ. AsEnumerable(). First() mi ottiene quindi il primo elemento per Ordine.

4

Si mescolano due punti: enumerazione e ordinamento.

Quando si enumera su IEnumerable non ci si deve preoccupare dell'ordine. Lavorate con l'interfaccia e la sua implementazione dovrebbe interessare l'ordine.

Per esempio:

void Enumerate(IEnumerable sequence) 
{ 
    // loop 
} 

SortedList<T> sortedList = ... 
Enumerate (sortedList); 

All'interno del metodo è ancora una lista con ordine fisso, ma il metodo non sa di particolare implementazione di interfaccia ed è peculiarità.

6

Forse stai cercando l'interfaccia IOrderedEnumerable? Viene restituito dai metodi di estensioni come OrderBy() e consente la successiva ordinamento con ThenBy().

+0

Sfortunatamente questo non funzionerà se si desidera accettare interfacce come IList che garantiscono un ordine ma non ereditano da IOrderedEnumerable. Vedi http://stackoverflow.com/q/5429974/1157054 – Ajedi32