2009-09-09 9 views
27

Quali sono le differenze chiave tra Dictionary.Clear e new Dictionary() in C#? Quale è consigliato per quali casi?Differenze tra Dictionary.Clear e nuovo dizionario()

+0

prestazioni correlate: [which-is-faster-clear-collection-or-instantiate-new] (http://stackoverflow.com/questions/10901020/which-is-faster-clear-collection-or-stantiate- nuovo) – nawfal

risposta

32

Dictionary.Clear() rimuoverà tutte le coppie KeyValue all'interno del dizionario. Fare new Dictionary() creerà una nuova istanza del dizionario.

Se, e solo se, la vecchia versione del dizionario non è radicata da un altro riferimento, la creazione di un nuovo dizionario farà sì che l'intero dizionario e il contenuto (che non sono radicati altrove) siano disponibili per la pulizia dal GC.

Dictionary.Clear() renderà disponibili le coppie KeyValue per la pulizia.

In pratica, entrambe le opzioni tenderanno ad avere effetti molto simili. La differenza sarà che cosa succede quando questo viene utilizzato all'interno di un metodo:

void NewDictionary(Dictionary<string,int> dict) 
{ 
    dict = new Dictionary<string,int>(); // Just changes the local reference 
} 

void ClearDictionary(Dictionary<string,int> dict) 
{ 
    dict.Clear(); 
} 

// When you use this... 
Dictionary<string,int> myDictionary = ...; // Set up and fill dictionary 

NewDictionary(myDictionary); 
// myDictionary is unchanged here, since we made a new copy, but didn't change the original instance 

ClearDictionary(myDictionary); 
// myDictionary is now empty 
+2

@divo - Penso che voglia dire una copia del riferimento, non una copia dell'oggetto stesso –

+0

@John: era esattamente ciò che intendevo. È una copia - una copia del riferimento al dizionario –

0

Dictionary.clear sfratterà tutti gli elementi nel dizionario. nuovo dizionario crea un nuovo oggetto dizionario in memoria mentre orfano il tuo precedente dizionario per il garbage collector per ripulire più tardi.

+0

Possiamo fare meglio di "molto probabilmente"? Questa sarà una domanda chiave qui. –

+0

Non penso che il dizionario chiamerà mai Dispose sugli oggetti che contiene; se gli articoli sono usa e getta penso che dovresti scrivere un codice esplicito per disporli. – ChrisW

+1

Perché chiamerebbe disporre di qualcosa? Solo perché sono in un dizionario non significa che non sono in uso altrove. Quello sarebbe orribilmente bacato. Tutto ciò che fa è null i bucket hashtable. – womp

14

Dictionary.Clear()
Questo rimuove tutte le coppie chiave/valore all'interno del dizionario. Il Garbage Collector cancellerà la memoria per questi articoli durante il prossimo ciclo di raccolta dei rifiuti. MSDN

nuovo dizionario()
Crea un nuovo oggetto Dictionary nella memoria e abbandona l'oggetto originale. La memoria verrebbe cancellata durante il prossimo ciclo di raccolta dei rifiuti.

+0

Questo articolo MSDN non dice nulla sullo smaltimento. –

+3

Qualcosa da considerare - se il tuo dizionario è molto grande, e sei sicuro che ti verrà caricato lo stesso circa dei dati dopo la cancellazione - il fatto che Dictionary.Clear() non resetta la capacità del dizionario farà è più attraente. – overslacked

+0

@overslacked - Accidenti Ho appena passato del tempo a scrivere una risposta che ha suggerito esattamente questo. – womp

5

Suppongo che la differenza fondamentale è che se si chiama Dictionary.Clear(), tutti i riferimenti a quel dizionario verranno cancellate. Se si utilizza new Dictionary(), il riferimento a cui si sta lavorando al momento verrà cancellato (in un certo senso), ma tutti gli altri posti in cui si hanno riferimenti non saranno poiché si riferiranno ancora al vecchio dizionario.

Speriamo che questo codice illustra semplicemente:

public void Method() 
{ 
    Dictionary<int, int> d1 = new Dictionary(); 

    d1.Add(1,1); 
    d1.Add(2,3); 

    Dictionary<int, int> d2 = d1; 

    //this line only 'clears' d1 
    d1 = new Dictionary(); 

    d1.Add(1,1); 
    d1.Add(3,5); 
    d2.Add(2,2); 

    //writes '2' followed by '1' 
    Console.WriteLine(d1.Count); 
    Console.WriteLine(d2.Count); 
} 

Se avessi chiamato d1.Clear() invece, poi D1 e D2 sarei rimasto in sincronia, e la successiva aggiunge avrebbe aggiunto ad entrambi. Le chiamate WriteLine avrebbero entrambe output '3'.

+0

+1 - questa è la differenza fondamentale. – Joe

1

Se si dispone di più riferimenti a quel dizionario e lo si deseleziona, si influirà su tutti i punti in cui, come se si crea un nuovo dizionario, si influirà solo su un nuovo riferimento. Immagino dipenda dalla portata dell'impatto che stai mirando. Ovviamente una chiamata a "nuovo" ti darà un dizionario "cancellato" ma potresti perdere altre utili informazioni di stato.

5

Dictionary.Clear rimuoverà (ma non disporrà) tutti gli elementi nell'istanza mentre new Dictionary() creerà una nuova istanza che sembra essere vuota. Ci possono essere delle sottili implicazioni tra i due. Considera i seguenti esempi.

void Example1() 
{ 
    var collection = new Dictionary<string, string>(); 
    collection.Add("key1", "value1"); 
    collection.Add("key2", "value2"); 
    foreach (var kvp in collection) 
    { 
    collection = new Dictionary<string, string>(); 
    Console.WriteLine(kvp); 
    } 
} 

void Example2() 
{ 
    var collection = new Dictionary<string, string>(); 
    collection.Add("key1", "value1"); 
    collection.Add("key2", "value2"); 
    foreach (var kvp in collection) 
    { 
    collection.Clear(); 
    Console.WriteLine(kvp); 
    } 
} 

Nel primo esempio verranno stampati tutti i contenuti della raccolta originale.Questo perché l'enumeratore è stato creato dalla variabile di riferimento prima di essere riassegnato a una nuova istanza.

Nel secondo esempio la raccolta viene cancellata durante un'enumerazione che risulterà in un InvalidOperationException perché la raccolta è stata modificata.

19

Come è stato ampiamente trattato, gli effetti sono essenzialmente gli stessi. Clear() e new entrambi ti daranno un nuovo dizionario, essenzialmente abbandonando i riferimenti agli oggetti al suo interno, liberandoli per essere raccolti se sono stati sradicati.

Tecnicamente, .Clear() avrebbe un vantaggio rispetto a new se si stava per ripopolare il dizionario alle stesse dimensioni come era prima. Questo perché sarebbe già stato ridimensionato internamente per contenere il numero di oggetti che avevi in ​​precedenza. La creazione di un nuovo dizionario dovrebbe avere una nuova tabella hash interna con le dimensioni predefinite e dovrebbe essere ri-espansa man mano che gli elementi aggiunti vengono aggiunti.

Vorrei anche suggerire che comunicano un intento completamente diverso, e dovresti usare .Clear() nel tuo codice quando hai a che fare con lo stesso contesto di prima. La creazione di un nuovo dizionario implica che stai per intraprendere qualche nuova logica che riguarda qualcosa di diverso dal vecchio dizionario, mentre usare Clear() indica che sì, volevi davvero resettare tutto ciò che hai fatto finora.

+4

> La creazione di un nuovo dizionario dovrebbe avere una nuova tabella hash interna con le dimensioni predefinite, non necessariamente, è possibile utilizzare un sovraccarico costruttore per impostare la capacità iniziale. – Joe

+4

Sì. Stavo assumendo solo un .Clear() contro un nuovo dizionario(). – womp

3

Credo che .Clear() è stato fornito in modo che se il tuo dizionario è esposto come una proprietà di sola lettura si sarebbe in grado di rimuovere tutti gli elementi. Tuttavia, se non è esposto in questo modo e hai il controllo completo, potrebbe essere più semplice istanziare un nuovo dizionario. Ci potrebbe essere una leggera differenza di prestazioni tra i due, anche.