2016-04-13 17 views
5

Mentre osservavo l'implementazione di List.AddRange ho trovato qualcosa di strano che non capisco. Sourcecode, see line 727 (AddRange chiama InsertRange)List <T> .AddRange/InsertRange creazione array temporaneo

T[] itemsToInsert = new T[count]; 
c.CopyTo(itemsToInsert, 0); 
itemsToInsert.CopyTo(_items, index); 

Perché fai l'copiarlo la raccolta in un "temp-array" (itemsToInsert) e poi copia l'array temporaneo nella attuale _items-array? C'è qualche motivo alla base di questo, o si tratta solo di alcuni residui dalla copia della sorgente di ArrayList, perché la stessa cosa accade lì.

+2

Suppongo che sia per passare gli articoli in base al valore anziché per riferimento in modo che gli elementi originali inseriti non vengano modificati nel caso in cui gli elementi all'interno dell'elenco vengano modificati –

+1

@Jdsfighter - Non vedo come aiuta a tutti. I contenuti di un array o di una collezione sono valori o riferimenti. Il codice sopra non fa nulla per cambiare la natura di ciò che viene copiato. –

+0

Non penso davvero che sia per nascondere l'array sottostante. Nella mia risposta ho indicato altre probabili spiegazioni. – Fabjan

risposta

4

La mia ipotesi è che questo per nascondere l'esistenza dell'array di supporto interno. Non c'è modo di ottenere un riferimento a quell'array che è intenzionale. La classe non promette nemmeno che esiste una tale matrice. (Naturalmente, per le prestazioni e per motivi di compatibilità, verrà sempre implementato con un array.)

Qualcuno potrebbe passare in un ICollection<T> creato che memorizza la matrice che viene passata. Ora i chiamanti possono pasticciare con l'array interno di List e iniziare in base agli interni di List.

Contrasto con MemoryStream che ha un modo documentato per accedere al buffer interno (e spararsi con esso): GetBuffer().

+0

Se questa è la vera ragione, allora non vedo il punto: qualcuno potrebbe anche usare la riflessione per cercare i campi dell'array privato se vogliono fare confusione con le cose. –

+0

Usando il riflesso è possibile aprire qualsiasi cosa ma è più difficile e succede più raramente nella pratica. Questa sembra essere una protezione contro l'uso improprio di API accidentali o incauti. Il codice chiamante inizia invariabilmente a dipendere dagli invarianti che sono veri ora ma non sono garantiti. Più difficile è questo, più sarà raro. – usr

+1

Creare una collezione che ricordi gli array con l'intenzione di fare scherzi con gli interni non è molto più comune, direi. Stessa intenzione in realtà, e non qualcosa che penso valga la pena di proteggere in una biblioteca di uso generale. EDIT: Vedo, questo protegge da determinati abusi accidentali. Dopotutto non è così inverosimile dato quanto viene usato List. –