2010-09-24 11 views
9

È vero che le raccolte generiche offrono risultati migliori rispetto alle raccolte non generiche per i tipi di valore. (es. Lista contro ListaMateriale).Dove sono archiviati i tipi di valore in (C#) Raccolte generiche

Ma perché, oltre al passaggio di boxing-unboxing? Dove sono memorizzati gli oggetti del tipo valore una volta aggiunti alla raccolta? Nelle raccolte non generiche, verranno archiviati e archiviati nell'heap, cosa c'è di diverso nei generici?

+0

Per lo stesso numero di numeri interi, sizeof (Lista ) ~ = sizeof (int []) ~ = 1/2 sizeof (ArrayList su x86) ~ = 1/3 sizeof (ArrayList su x86-64). Inoltre, la localizzazione dei dati fa schifo su ArrayList a causa del pugilato e produce una frammentazione della memoria superiore alla necessaria. –

risposta

1

Un ArrayList è un array locale di riferimenti agli oggetti memorizzati nell'heap.

Un elenco generico di tipi di riferimenti è un array locale di riferimenti agli oggetti memorizzati nell'heap.

Un elenco generico di tipi di valore è un array locale di tali tipi di valore.

Ci sono due aree di memoria, che la maggior parte dei riferimenti chiama "The Stack" e "The Heap". La maggior parte delle persone che usano questi termini non hanno idea del perché. ("The Stack" potrebbe essere una pila, ma The Heap quasi certamente non è un mucchio). Preferisco i termini "Over Here" e "Over There". Se inserito in una scatola, i dati del tipo di valore sono memorizzati "Over There". Se memorizzato in un array (forse all'interno di un Elenco generico), i dati del tipo di valore vengono memorizzati "Over Here". "Qui è meglio".

+0

"Qui" - "Laggiù" ??? Che cosa???? E cos'è un "array locale"? Questa risposta è più confusa di qualsiasi altra cosa. –

+0

@ 0xA3: un array locale è uno che è memorizzato in "The Stack". È più illuminante formulato in quel modo? –

+2

OK, la tua affermazione non è corretta (se intendi lo stack nel senso comunemente usato).Sia 'ArrayList' che' List 'utilizzano un oggetto System.Array come memoria interna che è un tipo di riferimento e viene memorizzato" là ". –

11

In generici, ad esempio List<T>, sono ancora memorizzati nell'heap. La differenza è che, internamente, un List<int> crea un singolo array di numeri interi e può memorizzare direttamente i numeri. Con ArrayList, si finisce per memorizzare una serie di riferimenti a valori interi in box.

0

I guadagni in termini di prestazioni generici sono in genere solo per quanto riguarda i tipi di valore utilizzati con generici rispetto ai tipi di valore memorizzati in equivalenti non generici.

Questo perché con i tipi di valore generici non è necessario eseguire il cast su oggetto e archiviato nell'heap (in scatola). In realtà possono rimanere in pila, che è più performante.

http://msdn.microsoft.com/en-us/library/ms172181.aspx

8

Il relativo dettaglio attuazione è che all'archiviazione sottostante per un List<T> è una T []. Quindi per uno List<int> i valori saranno memorizzati in un []. Gli interi sono memorizzati in un blocco contiguo di memoria, allocati dall'heap garbage collocato.

Ciò che lo rende così veloce non è solo il fatto che gli interi non sono in scatola, è che un int [] funziona così bene con la cache della CPU. Quando leggi il primo elemento, ottieni in pratica i successivi 15 senza dover leggere la RAM lenta o la cache secondaria. Questo funziona non così bene per un int incantato perché è così grande e il riferimento extra può avere una scarsa localizzazione della cache. Tuttavia, il garbage collector aiuta davvero a liberarsi da quel costo comprimendo l'heap.

+0

Ah, l'unica risposta che afferma esplicitamente che 'Lista ' in effetti utilizza un array come backing store (e ben inserito anche). Un 'List ' è semplicemente un wrapper per una matrice che aggiunge il supporto per il ridimensionamento, e in effetti quasi tutti i tipi di raccolta arrivano agli array, ad eccezione delle raccolte speciali come 'LinkedList '. –

+0

Quindi un 'ArrayList' ha un doppio risultato in termini di prestazioni. Per prima cosa devi dereferenziare il valore dall'array per ottenere l'oggetto (tipo valore in box), e quindi devi annullarlo. –

+0

Ma se l'archivio di supporto per 'ArrayList' è' object [] ', prima devi cercare l'elemento nell'array, che ti dà un riferimento all'oggetto che contiene l'int. Devi dereferenziare che per ottenere l'oggetto, devi eliminarlo. Confrontalo con 'List', dove tutto ciò che devi fare è prendere l'oggetto dal backing store 'int []'. –

Problemi correlati