Strutture di dati .NET:
Altro sulla conversazione sul perché ArrayList e List sono effettivamente diversi
Array
Come afferma un utente, gli array sono la raccolta "vecchia scuola" (sì, gli array sono considerati una raccolta anche se non fanno parte di System.Collections
). Ma che cos'è la "vecchia scuola" riguardo alle matrici rispetto ad altre raccolte, cioè quelle che hai elencato nel tuo titolo (qui, ArrayList and List (Of T))? Cominciamo con le basi guardando Array.
Per iniziare, gli array in Microsoft .NET sono "meccanismi che consentono di trattare diversi elementi [logicamente correlati] come un'unica raccolta" (vedere l'articolo collegato). Cosa significa? Gli array memorizzano i singoli membri (elementi) in sequenza, uno dopo l'altro in memoria con un indirizzo iniziale. Usando l'array, possiamo facilmente accedere agli elementi memorizzati in sequenza a partire da quell'indirizzo.
Oltre a ciò e contrariamente alla programmazione di 101 concezioni comuni, gli array possono davvero essere piuttosto complessi:
Le matrici possono essere monodimensionali, multidimensionali o jadded (vale la pena leggere le matrici frastagliate). Gli array stessi non sono dinamici: una volta inizializzato, un array di n dimensioni riserva spazio sufficiente per contenere n numero di oggetti. Il numero di elementi nell'array non può aumentare o diminuire. Dim _array As Int32() = New Int32(100)
riserva spazio sufficiente sul blocco di memoria affinché l'array contenga 100 oggetti di tipo primitivo Int32 (in questo caso, l'array viene inizializzato per contenere 0s). Viene restituito l'indirizzo di questo blocco _array
.
Secondo l'articolo, Common Language Specification (CLS) richiede che tutti gli array siano a base zero. Le matrici in .NET supportano matrici non basate su zero; tuttavia, questo è meno comune. Come risultato del "carattere comune" degli array a base zero, Microsoft ha trascorso molto tempo a ottimizzare le proprie prestazioni ; pertanto, gli array a dimensione singola, a base zero (SZ) sono "speciali" - e in realtà la migliore implementazione di un array (al contrario di multidimensionali, ecc.) - perché gli SZ hanno istruzioni linguistiche intermedie specifiche per manipolarli.
Le matrici vengono sempre passate per riferimento (come indirizzo di memoria), un pezzo importante del puzzle di matrice da conoscere. Mentre eseguono il controllo dei limiti (genererà un errore), il controllo dei limiti può anche essere disabilitato sugli array.
Ancora una volta, il più grande ostacolo alle matrici è che non sono ridimensionabili. Hanno una capacità "fissa". Presentazione di ArrayList and List (Of T) alla nostra storia:
ArrayList - elenco non generico
The ArrayList (insieme a List(Of T)
- sebbene ci siano alcune differenze critiche, qui, spiegate più avanti) - è forse meglio pensato come la prossima aggiunta alle collezioni (in senso lato). ArrayList eredita dall'interfaccia IList (un discendente di 'ICollection'). Gli elenchi di array, a loro volta, sono più voluminosi - richiedono un overhead maggiore rispetto agli elenchi.
IList
consente all'implementazione di trattare gli ArrayList come elenchi di dimensioni fisse (come gli Array); tuttavia, al di là della funzionalità aggiuntiva aggiunta da ArrayLists, non vi sono reali vantaggi nell'uso di ArrayList di dimensioni fisse poiché ArrayLists (su Array) in questo caso sono notevolmente più lenti.
Dalla mia lettura, ArrayLists non può essere frastagliato: "L'uso di array multidimensionali come elementi ... non è supportato". Ancora una volta, un altro chiodo nella bara di ArrayLists. ArrayLists non sono anche "digitato" - il che significa che, al di sotto di tutto, un ArrayList è semplicemente un array dinamico di oggetti: Object[]
. Ciò richiede un sacco di boxe (implicito) e unboxing (esplicito) durante l'implementazione di ArrayLists, aggiungendo di nuovo al loro overhead.
Pensiero non comprovato: penso di ricordare di aver letto o di aver sentito da uno dei miei professori che ArrayLists è una specie di figlio concettuale bastardo del tentativo di spostarsi dalle matrici alle raccolte di tipo elenco, vale a dire mentre una volta era stato un grande miglioramento per le matrici, non sono più l'opzione migliore poiché sono stati fatti ulteriori sviluppi rispetto alle collezioni
Elenco (di T): ciò che ArrayList è diventato (e sperava di essere)
La differenza nell'uso della memoria è abbastanza significativa da dove un Elenco (di Int32) consumava il 56% di memoria in meno rispetto a un ArrayList contenente lo stesso tipo primitivo (8 MB contro 19 MB nella dimostrazione collegata del gentleman sopra: di nuovo, collegata qui ) - sebbene questo è un risultato aggravato dalla macchina a 64 bit. Questa differenza dimostra davvero due cose: primo (1), un "oggetto" di tipo Int32 in scatola (ArrayList) è molto più grande di un tipo primitivo Int32 puro (Elenco); secondo (2), la differenza è esponenziale a causa del funzionamento interno di una macchina a 64 bit.
Quindi, qual è la differenza e cos'è un elenco (di T) ? MSDN definisce un List(Of T)
", un elenco fortemente tipizzato di oggetti a cui è possibile accedere tramite indice." L'importanza qui è il bit "fortemente tipizzato": un elenco (di T) "riconosce" i tipi e memorizza gli oggetti come loro tipo. Quindi, un Int32
viene memorizzato come tipo Int32
e non come Object
tipo. Questo elimina i problemi causati da boxe e unboxing.
MSDN specifica che questa differenza entra in gioco solo quando si memorizzano tipi primitivi e non tipi di riferimento. Anche la differenza si verifica davvero su larga scala: oltre 500 elementi. La cosa più interessante è che la documentazione MSDN riporta "È vantaggioso utilizzare l'implementazione specifica del tipo della classe List (Of T) invece di usare la classe ArrayList ...."
In sostanza, List (Of T) è ArrayList, ma migliore. È "l'equivalente generico" di ArrayList. Come ArrayList, non è garantito che vengano ordinati fino a quando non vengono ordinati (vai alla figura). List (Of T) ha anche alcune funzionalità aggiunte.