Sto usando .Net 3.5 (C#) e ho sentito che la performance di C# List<T>.ToArray
è "cattiva", poiché la memoria copia tutti gli elementi per formare una nuova matrice. È vero?C# List <T>. Le prestazioni dell'Array sono errate?
risposta
No che non è vero. Le prestazioni sono buone poiché tutto ciò che fa è la memoria copia tutti gli elementi (*) per formare un nuovo array.
Ovviamente dipende da ciò che definite prestazioni "buone" o "cattive".
(*) riferimenti per tipi di riferimento, valori per tipi di valore.
EDIT
In risposta al tuo commento, utilizzando Reflector è un buon modo per verificare l'attuazione (vedi sotto). Oppure pensa solo per un paio di minuti a come lo implementeresti e prendi fiducia che gli ingegneri di Microsoft non escano con una soluzione peggiore.
public T[] ToArray()
{
T[] destinationArray = new T[this._size];
Array.Copy(this._items, 0, destinationArray, 0, this._size);
return destinationArray;
}
Naturalmente, le prestazioni "buone" o "cattive" hanno solo un significato relativo ad alcune alternative. Se nel tuo caso specifico, esiste una tecnica alternativa per raggiungere il tuo obiettivo che è misurabilmente più veloce, allora puoi considerare la performance come "cattiva". Se non esiste tale alternativa, le prestazioni sono "buone" (o "abbastanza buone").
EDIT 2
In risposta al commento: "No ri-costruzione di oggetti?":...
n ricostruzione per i tipi di riferimento per tipi di valori vengono copiati i valori, che possono liberamente essere descritto come ricostruzione
Grazie Joe, la tua risposta è così bella!Avete dei documenti correlati per discutere ulteriormente o provare ulteriormente il reclamo - "tutto ciò che fa è la memoria copia tutti gli elementi (*) per formare un nuovo array."? – George2
Grazie a Joe, Array.Copy copia solo il riferimento? Nessuna ri-costruzione di oggetti? – George2
George. Vai a cercare! Oppure vai a usare Reflector e scoprilo. Non era così complesso per ToArray, vero? –
crea nuovi riferimenti in un array, ma questo è solo l'unica cosa che questo metodo potrebbe e dovrebbe fare ...
Vuoi dire che solo il riferimento viene copiato? – George2
motivi per chiamare ToArray()
- Se il valore restituito non è pensato per essere modificato, restituirlo come una matrice rende questo fatto un po 'più chiaro.
- Se si prevede che il chiamante esegua molti accessi non sequenziali ai dati, ci può essere un vantaggio in termini di prestazioni per un array su un elenco <>.
- Se si sa che sarà necessario passare il valore restituito a una funzione di terze parti che si aspetta un array.
- Compatibilità con le funzioni di chiamata che devono funzionare con .NET versione 1 o 1.1. Queste versioni non hanno il tipo List <> (o qualsiasi tipo generico, per quello).
Motivi di non chiamare ToArray()
- Se il chiamante mai ha bisogno di aggiungere o rimuovere elementi, un elenco <> è assolutamente necessaria.
- I vantaggi prestazionali non sono necessariamente garantiti, soprattutto se il chiamante accede ai dati in modo sequenziale. C'è anche il passaggio aggiuntivo per la conversione da Lista <> alla matrice, che richiede tempo di elaborazione.
- Il chiamante può sempre convertire l'elenco in una matrice.
tratto da here
Un buon riferimento, ma non una risposta diretta alla mia domanda? Qual è la tua risposta alla mia domanda? – George2
È l'unica risposta che possiamo dare: la correttezza vince sempre sulle prestazioni. Non è la cosa più performante che puoi ancora corretta. L'applicazione di questo è che non si chiama .ToArray() a meno che non si debba comunque. –
"... può esserci un vantaggio in termini di prestazioni per un array su un elenco <>." - nessuna prova per questo? Sembra un mito per me. – Joe
prestazioni deve essere intesa in termini relativi Conversione di un array a una lista comporta la copia del array, e il costo dipende dalla dimensione dell'array, ma è necessario confrontare il costo con altre cose che il programma sta facendo. Come hai ottenuto le informazioni da inserire nell'array in primo luogo? era leggendo dal disco, o una connessione di rete, o un database, quindi una copia di matrice in memoria è molto improbabile per fare una differenza rilevabile per il tempo impiegato
"inserire nell'array in primo luogo" significa? – George2
Prima di copiare l'array, è necessario aver ottenuto alcune informazioni da archiviare nell'array, altrimenti non ci sarebbe motivo di crearne una copia. –
Sì , è vero che fa una copia di memoria di tutti gli elementi. È un problema di prestazioni? Dipende dai tuoi requisiti di prestazione.
A List
contiene un array internamente per contenere tutti gli elementi. L'array cresce se la capacità non è più sufficiente per l'elenco. Ogni volta che succede, la lista copierà tutti gli elementi in una nuova matrice. Succede sempre e per la maggior parte delle persone non ci sono problemi di prestazioni.
E.g. una lista con un costruttore predefinito inizia alla capacità 16, e quando si usa l'elemento 17, .Add()
, si crea una nuova matrice di dimensione 32, copia i 16 valori precedenti e aggiunge la diciassettesima.
La differenza di dimensione è anche il motivo per cui ToArray()
restituisce una nuova istanza di matrice invece di passare il riferimento privato.
Grazie chris166, voglio solo confermare che solo il riferimento è stato copiato durante ToArray. Nessuna ri-costruzione di oggetti durante ToArray? – George2
Sì, vengono copiati solo i riferimenti. L'elenco non sa come creare una copia profonda dei tuoi oggetti. L'eccezione sono i tipi di valore (structs, ints, double, enum etc). – chris166
Per qualsiasi tipo di elenco/ICollection in cui conosce la lunghezza, può allocare una matrice della dimensione esatta fin dall'inizio.
T[] destinationArray = new T[this._size];
Array.Copy(this._items, 0, destinationArray, 0, this._size);
return destinationArray;
Se il tipo di origine è IEnumerable (non una lista/Collection), allora la fonte è:
items = new TElement[4];
..
if (no more space) {
TElement[] newItems = new TElement[checked(count * 2)];
Array.Copy(items, 0, newItems, 0, count);
items = newItems;
Si inizia alle dimensioni 4 e cresce in modo esponenziale, raddoppiando ogni volta che si esaurisce lo spazio. Ogni volta che raddoppia, deve riallocare la memoria e copiare i dati.
Se conosciamo la dimensione dei dati di origine, possiamo evitare questo leggero sovraccarico. Tuttavia, nella maggior parte dei casi, ad esempio la dimensione dell'array < = 1024, verrà eseguita così rapidamente che non è nemmeno necessario pensare a questi dettagli di implementazione.
Riferimenti: Enumerable.cs, List.cs (F12ing in loro), la risposta di Joe
- 1. La chiusura e la riapertura delle istanze di Realm sono errate per le prestazioni?
- 2. Come utilizzare l'espressione del generatore CMake $ <TARGET_FILE: tgt>?
- 3. C# List <> di xml
- 4. C# List <T> Contiene test
- 5. Prestazioni errate OpenGL in Android Gingerbread
- 6. C# ottenere le chiavi e valori da List <KeyValuePair <string, string>
- 7. Le proprietà di impostazione sull'oggetto Window sono considerate pratiche errate?
- 8. Perché le frasi "continue" sono errate in JavaScript?
- 9. C# List <T> .ConvertAll in .NET 2.0
- 10. python: confronto tra prestazioni deque vs list
- 11. Come ottenere la conversione da List <SomeParamType> a List <SomeParamType <?>>
- 12. Haskell: sintonizzazione delle prestazioni list/vector/array
- 13. Le prestazioni di fragmenttabhost sono lente?
- 14. come utilizzare esistere in List <string> in C#
- 15. C# Come restituire List <> Come JSON
- 16. Prestazioni errate su Azure per l'applicazione Owin/IIS
- 17. Come sono le prestazioni quando ci sono centinaia di Task.Delay
- 18. Cluster Cassandra con prestazioni errate nell'inserto e stabilità dell'inserto
- 19. Amazon S3: quali sono le richieste PUT/COPY/POST/LIST?
- 20. DataTable to List <object>
- 21. Serializing List <> con XmlSerializer
- 22. Come eseguire il cast List <Map<?, ?>> in List <Map <String, String >>?
- 23. Perché le eccezioni sono dannose per le prestazioni?
- 24. Le visualizzazioni "GONE" sono dannose per le prestazioni?
- 25. Informazioni su Android <layer-list>
- 26. Casting List <> of Derived class to List <> of base class
- 27. Converti StringCollection to List <String>
- 28. Questi esempi sono le chiusure C#?
- 29. Correggere le ellissi errate in una stringa
- 30. C List # Casting <ushort> la lista <short>
Si potrebbe desiderare di vedere [è-da-meglio-to-call-ToList-o-ToArray-in-linq- query] (http://stackoverflow.com/questions/1105990/is-it-better-to-call-tolist-or-toarray-in-linq-queries) – nawfal