2009-05-18 50 views
95

Eventuali duplicati:
Why Dictionary is preferred over hashtable in C#?Differenza tra Dizionario e Hashtable

Qual è la differenza tra il Dizionario e Hashtable. Come decidere quale usare?

+2

Sembra che questa domanda debba essere chiusa come duplicata e le sue risposte unite con uno dei duplicati. –

+0

si spera che risponda a questa [domanda] (http://stackoverflow.com/questions/301371/why-dictionary-is-preferred-over-hashtable-in-c) fornisce una buona risposta – TheVillageIdiot

+0

Anche se relativa al linguaggio java ma [ this] (https://stackoverflow.com/q/40471/465053) vale la pena di leggere il thread per conoscere la differenza tra 'HashMap' e' HashTable'. Poche differenze si applicano anche al mondo C#. – RBT

risposta

185

Semplicemente, Dictionary<TKey,TValue> è un tipo generico, permettendo:

  • tipizzazione statica (e compilare in tempo di verifica)
  • uso senza la boxe

Se siete .NET 2.0 o superiore, devi preferisciDictionary<TKey,TValue> (e le altre raccolte generiche)

Un sottile ma io la differenza importante è che Hashtable supporta più thread di lettura con un singolo thread di scrittura, mentre Dictionary non offre alcuna sicurezza di thread. Se è necessaria la sicurezza del thread con un dizionario generico, è necessario implementare la propria sincronizzazione o (in .NET 4.0) utilizzare ConcurrentDictionary<TKey, TValue>.

+3

Ma i metodi di istanza del dizionario non sono thread-safe, a differenza di Hashtable – t3mujin

11

Il dizionario è tipizzato (quindi i tipi di valore non hanno bisogno di boxe), un Hashtable non lo è (quindi i tipi di valore richiedono la boxe). Hashtable ha un modo più bello di ottenere un valore rispetto al dizionario IMHO, perché sa sempre che il valore è un oggetto. Anche se stai usando .NET 3.5, è facile scrivere un metodo di estensione per il dizionario per ottenere un comportamento simile.

Se avete bisogno di più valori per ogni chiave, controllare il mio codice sorgente di MultiValueDictionary qui: multimap in .NET

+2

Per più valori per chiave: in .NET 3.5, si potrebbe anche considerare l'implementazione di 'ILookup ' (che è l'interfaccia multi-mappa). Sfortunatamente l'implementazione concreta di default è immutabile, ma è facile da implementare (o aggiungere al tuo MultiValueDictionary). C'è un semplice esempio di tale in MiscUtil (EditableLookup ) –

+0

Un buon consiglio, in effetti, mi ero dimenticato di quell'interfaccia. Ho esaminato l'implementazione nel BCL, ma è davvero immutabile, quindi praticamente inutile per l'utilizzo multi-valore di tutti i giorni;). Aggiungerò l'interfaccia. –

+0

Fatto. Ripubblicato codice: http://weblogs.asp.net/fbouma/archive/2009/05/18/multi-value-dictionary-c-source-code-net-3-5.aspx –

6

La classe Hashtable è un tipo specifico di classe dizionario che utilizza un valore intero (chiamato un hash) per favorire la memorizzazione delle sue chiavi. La classe Hashtable utilizza l'hash per accelerare la ricerca di una chiave specifica nella raccolta. Ogni oggetto in .NET deriva dalla classe Object. Questa classe supporta il metodo GetHash, che restituisce un numero intero che identifica in modo univoco l'oggetto. La classe Hashtable è una raccolta molto efficiente in generale. L'unico problema con la classe Hashtable è che richiede un po 'di overhead e che per le piccole raccolte (meno di dieci elementi) il sovraccarico può impedire le prestazioni.

v'è una certa differenza speciale tra due che deve essere considerato:

HashTable: è la raccolta non generico, il più grande testa di questa collezione è che lo fa boxe automaticamente i vostri valori e al fine per ottenere il valore originale è necessario eseguire unboxing, per ridurre le prestazioni dell'applicazione come penalità.

Dictionary: Questo è il tipo generico di raccolta in cui non implicita boxe, quindi nessun bisogno di unboxing si sempre ottenere il vostro valori originali che si erano conservati in modo che migliorerà la vostra applicazione prestazioni.

la differenza Seconda Notevole è:

se la stavano cercando di accedere ad un valore dalla tabella hash sulla base di chiave che non esiste tornerà null.But nel caso di Dizionario lo farà darti KeyNotFoundException.

+0

I miei commenti provengono dal libro di MCTS 2.0 e il suo rappresentante ottenuto - ve ... che ironia !!!! : D –

+2

Non proprio molto ironico ... sia Hashtable che Dizionario <,> sono basati su questo approccio, quindi non rispondono in alcun modo alla domanda di scelta tra di loro. –

+4

La vera ironia è che stavo leggendo lo stesso libro MCTS, mi sono davvero confuso su quale preferire, lo ho postato qui e ho ottenuto lo stesso testo che ho appena letto nella forma della tua risposta !!! :) Grazie per aver risposto nyways .. – blitzkriegz

19

C'è ancora una differenza importante tra un HashTable e un dizionario. Se usi gli indicizzatori per ottenere un valore da una HashTable, l'HashTable restituirà un valore null per un elemento inesistente, mentre il dizionario genererà un errore se proverai ad accedere a un elemento utilizzando un indicizzatore che non esiste nel dizionario

3

L'interfaccia ILookup viene utilizzata in .net 3.5 con linq.

HashTable è la classe base di tipo debole; la classe astratta astratta viene digitata in modo esteso e utilizza internamente una HashTable.

Ho trovato una cosa strana sul dizionario, quando aggiungiamo le voci multiple nel dizionario, l'ordine in cui vengono aggiunte le voci viene mantenuto. Quindi se applico un foreach sul Dizionario, otterrò i record nello stesso ordine in cui li ho inseriti.

Considerando che questo non è vero con HashTable normale, come quando aggiungo stessi record in Hashtable l'ordine non viene mantenuto. Per quanto ne so, il dizionario è basato su Hashtable, se questo è vero, perché il mio dizionario mantiene l'ordine ma HashTable no?

Per quanto riguarda il motivo per cui si comportano in modo diverso, è perché il dizionario generico implementa un hashtable, ma non è basato su System.Collections.Hashtable. L'implementazione del dizionario generico si basa sull'allocazione di coppie chiave-valore da un elenco. Questi vengono quindi indicizzati con i bucket hashtable per l'accesso casuale, ma quando restituiscono un enumeratore, passa semplicemente l'elenco in ordine sequenziale - che sarà l'ordine di inserimento a condizione che le voci non vengano riutilizzate.

Shiv Govind Birlasoft. :)

75

Consente dare un esempio che potrebbe spiegare la differenza tra tabella hash e il dizionario.

Qui è un metodo che implementa tabella hash

public void MethodHashTable() 
{ 
    Hashtable objHashTable = new Hashtable(); 
    objHashTable.Add(1, 100); // int 
    objHashTable.Add(2.99, 200); // float 
    objHashTable.Add('A', 300); // char 
    objHashTable.Add("4", 400); // string 

    lblDisplay1.Text = objHashTable[1].ToString(); 
    lblDisplay2.Text = objHashTable[2.99].ToString(); 
    lblDisplay3.Text = objHashTable['A'].ToString(); 
    lblDisplay4.Text = objHashTable["4"].ToString(); 


    // ----------- Not Possible for HashTable ---------- 
    //foreach (KeyValuePair<string, int> pair in objHashTable) 
    //{ 
    // lblDisplay.Text = pair.Value + " " + lblDisplay.Text; 
    //} 
} 

Quello che segue è per la dizionario

public void MethodDictionary() 
    { 
    Dictionary<string, int> dictionary = new Dictionary<string, int>(); 
    dictionary.Add("cat", 2); 
    dictionary.Add("dog", 1); 
    dictionary.Add("llama", 0); 
    dictionary.Add("iguana", -1); 

    //dictionary.Add(1, -2); // Compilation Error 

    foreach (KeyValuePair<string, int> pair in dictionary) 
    { 
     lblDisplay.Text = pair.Value + " " + lblDisplay.Text; 
    } 
    } 
+5

Eccellente !!!!!!!!!!!!! – nawfal

+0

Super e semplice –

+3

Bella risposta. È sempre meglio spiegare attraverso gli esempi che la teoria della scrittura. – Kenta

10

desidera aggiungere una differenza:

Cercando di acess una chiave inesistente dà runtime errore nel dizionario ma nessun problema in hashtable in quanto restituisce null invece di errore.

ad es.

 //No strict type declaration 
     Hashtable hash = new Hashtable(); 
     hash.Add(1, "One"); 
     hash.Add(2, "Two"); 
     hash.Add(3, "Three"); 
     hash.Add(4, "Four"); 
     hash.Add(5, "Five"); 
     hash.Add(6, "Six"); 
     hash.Add(7, "Seven"); 
     hash.Add(8, "Eight"); 
     hash.Add(9, "Nine"); 
     hash.Add("Ten", 10);// No error as no strict type 

     for(int i=0;i<=hash.Count;i++)//=>No error for index 0 
     { 
      //Can be accessed through indexers 
      Console.WriteLine(hash[i]); 
     } 
     Console.WriteLine(hash["Ten"]);//=> No error in Has Table 

qui nessun errore per tasto 0 & anche per la chiave "dieci" (nota: t è piccolo)

//Strict type declaration 
     Dictionary<int,string> dictionary= new Dictionary<int, string>(); 
     dictionary.Add(1, "One"); 
     dictionary.Add(2, "Two"); 
     dictionary.Add(3, "Three"); 
     dictionary.Add(4, "Four"); 
     dictionary.Add(5, "Five"); 
     dictionary.Add(6, "Six"); 
     dictionary.Add(7, "Seven"); 
     dictionary.Add(8, "Eight"); 
     dictionary.Add(9, "Nine"); 
     //dictionary.Add("Ten", 10);// error as only key, value pair of type int, string can be added 

     //for i=0, key doesn't exist error 
     for (int i = 1; i <= dictionary.Count; i++) 
     { 
      //Can be accessed through indexers 
      Console.WriteLine(dictionary[i]); 
     } 
     //Error : The given key was not present in the dictionary. 
     //Console.WriteLine(dictionary[10]); 

qui di errore per tasto 0 & anche per la chiave 10 in quanto entrambi sono inesistente dizionario , errore di runtime, mentre provi ad accedere.

+0

Suppongo che dovresti usare 'LINQ' per trova l'elemento 'FirstOrDefault' se stai provando a lavorare con una raccolta esterna foreach e for. – ppumkin