2009-12-03 19 views
58

Was ist der Unterschied in Dictionary.add(key, value) und Dictionary[key] = value?Verschiedene Möglichkeiten zum Hinzufügen zum Wörterbuch

Ich habe festgestellt, dass die letzte Version keine ArgumentException wirft, wenn Sie einen doppelten Schlüssel einfügen, aber gibt es einen Grund, die erste Version zu bevorzugen?

Bearbeiten: Hat jemand eine maßgebliche Informationsquelle dazu? Ich habe MSDN versucht, aber es ist wie immer eine Reihe von Ungereimtheiten :(

Antwort

76

Die Leistung ist fast zu 100% identisch. Sie können dies überprüfen, indem Sie die Klasse in Reflector öffnen.net

Dies ist das Dieses Indexer:

public TValue this[TKey key] 
{ 
    get 
    { 
     int index = this.FindEntry(key); 
     if (index >= 0) 
     { 
      return this.entries[index].value; 
     } 
     ThrowHelper.ThrowKeyNotFoundException(); 
     return default(TValue); 
    } 
    set 
    { 
     this.Insert(key, value, false); 
    } 
} 

Und das ist die Add-Methode:

public void Add(TKey key, TValue value) 
{ 
    this.Insert(key, value, true); 
} 

Ich werde die gesamte Insert-Methode nicht veröffentlicht, sobald sie ziemlich lang sind, aber die Methode Erklärung das ist:

private void Insert(TKey key, TValue value, bool add) 

Und weiter unten in der Funktion, dies geschieht:

Die prüft, ob der Schlüssel bereits existiert, und wenn dies der Fall ist und der Parameter add wahr ist, löst er die Ausnahme aus.

Also für alle Zwecke und Absichten ist die Leistung gleich.

Wie bei einigen anderen Erwähnungen geht es nur darum, ob Sie die Prüfung benötigen, wenn Sie versuchen, denselben Schlüssel zweimal hinzuzufügen.

Sorry für die lange Post, ich hoffe es ist in Ordnung.

+0

+1 Sehr interessant, danke für Ihren Beitrag! Es scheint, dass die Leistung hier fast identisch ist, wie die anderen Plakate angedeutet haben, jedenfalls großartig finde :) –

0

In Anbetracht des meisten als wahrscheinlich Ähnlichkeiten in der Leistung, Verwendung, was auch immer das Gefühl mehr richtig und gut lesbar auf das Stück Code, die Sie verwenden.

ich fühle mich eine Operation, die eine Ergänzung beschreibt das Vorhandensein des Schlüssels ist schon eine wirklich seltene Ausnahme am besten mit dem Add vertreten ist. Semantisch macht es mehr Sinn.

die dict[key] = value stellt besser eine Substitution. Wenn ich sehe, dass Code ich Hälfte erwarte, dass der Schlüssel bereits im Wörterbuch sowieso ist.

+0

Ich würde davon ausgehen, gibt es eine kleine Leistungssteigerung von nicht überprüft, ob der Schlüssel zuerst existiert. Ich würde nicht von 'dic [key] = Wert erwarten, dass der Schlüssel bereits vorhanden war, aber ich denke, das ist umstritten;) –

+2

+ ich denke, dass werfen sollte nie als eine Möglichkeit zur Überprüfung verwendet werden, ob der Schlüssel bereits vertreten ist. if (! Strings.ContainsKey ("foo")) strings.Add ("foo", "bar"); – hhravn

51

Die erste Version fügt dem Wörterbuch eine neue KeyValuePair hinzu, wenn der Schlüssel bereits im Wörterbuch ist. Die zweite, die den Indexer verwendet, fügt ein neues Paar hinzu, wenn der Schlüssel nicht existiert, überschreibt jedoch den Wert des Schlüssels, falls er bereits im Wörterbuch vorhanden ist.

+0

+1 Haben Sie eine Quelle für die oben genannten Informationen? Ich bin daran interessiert zu erfahren, ob es irgendwelche Nebenwirkungen oder Vorbehalte bei der Verwendung der ersten oder späteren Form gibt. –

+3

Ich habe nicht wirklich eine Quelle als solche, nur aus dem Kopf, aber ich glaube nicht, dass es viel mehr gibt, als in den anderen Kommentaren erwähnt. Wenn ich mich richtig erinnere, verwendet Add einfach den Indexer, prüft aber zuerst, ob der Schlüssel bereits benutzt wird. – hhravn

+1

Geändert Antwort auf Steffen, weil seine Dokumentation erstklassig ist. Dies ist jedoch immer noch eine gute Antwort. –

4

Ja, das ist der Unterschied, die Add-Methode löst eine Ausnahme aus, wenn der Schlüssel bereits existiert.

Der Grund für die Verwendung der Add-Methode ist genau dies. Wenn das Wörterbuch den Schlüssel nicht bereits enthalten soll, möchten Sie normalerweise die Ausnahme, damit Sie auf das Problem aufmerksam gemacht werden.

+0

Klingt vernünftig :) –

20

Dictionary.Add(key, value) und Dictionary[key] = value dienen unterschiedlichen Zwecken:

  • Verwenden Sie die Add Methode neuen Schlüssel/Wert-Paar hinzufügen, werden vorhandene Schlüssel nicht ersetzt werden (ein ArgumentException geworfen).
  • Verwenden Sie den Indexer, wenn es Ihnen egal ist, ob der Schlüssel bereits im Wörterbuch vorhanden ist. Mit anderen Worten: Fügen Sie das Schlüssel/Wert - Paar hinzu, wenn der Schlüssel nicht im Wörterbuch ist, oder ersetzen Sie den Wert für den angegebenen Schlüssel Schlüssel befindet sich bereits im Wörterbuch.
0

Man weist einen Wert zu, während der andere dem Dictionary einen neuen Schlüssel und Wert hinzufügt.

9

Um die Frage zuerst zu beantworten, müssen wir uns den Zweck eines Wörterbuchs und der zugrunde liegenden Technologie ansehen.

Dictionary ist die Liste von KeyValuePair<Tkey, Tvalue>, wobei jeder Wert durch seinen eindeutigen Schlüssel dargestellt wird. Nehmen wir an, wir haben eine Liste Ihrer Lieblingsspeisen. Jeder Wert (Nahrungsname) wird durch seinen eindeutigen Schlüssel (eine Position = wie viel Sie dieses Essen mögen) dargestellt.

Beispielcode:

Dictionary<int, string> myDietFavorites = new Dictionary<int, string>() 
{ 
    { 1, "Burger"}, 
    { 2, "Fries"}, 
    { 3, "Donuts"} 
}; 

Angenommen, Sie gesund bleiben wollen, haben Sie Ihre Meinung geändert haben und Sie möchten Ihre Lieblings „Burger“ mit Salat ersetzen. Ihre Liste ist immer noch eine Liste Ihrer Favoriten, Sie werden die Art der Liste nicht ändern. Dein Favorit bleibt die Nummer eins auf der Liste, nur der Wert wird sich ändern. Dies ist, wenn Sie dies anrufen:

/*your key stays 1, you only replace the value assigned to this key 
    you alter existing record in your dictionary*/ 
myDietFavorites[1] = "Salad"; 

Aber vergessen Sie nicht, Sie sind der Programmierer, und ab jetzt beendet Sie Ihre Sätze mit; Sie verweigern die Verwendung von Emojis, weil sie einen Kompilierungsfehler auslösen würden und die Liste der Favoriten 0-basiert ist.

Ihre Diät hat sich auch geändert! So ändern Sie Ihre Liste wieder:

/*you don't want to replace Salad, you want to add this new fancy 0 
    position to your list. It wasn't there before so you can either define it*/ 
myDietFavorites[0] = "Pizza"; 

/*or Add it*/ 
myDietFavorites.Add(0, "Pizza"); 

Es gibt zwei Möglichkeiten, mit der Definition, Sie wollen entweder für etwas eine neue Definition geben, nicht vor existent, oder Sie wollen Definition ändern, die bereits vorhanden ist.

Mit der Add-Methode können Sie einen Datensatz hinzufügen, aber nur unter einer Bedingung: Der Schlüssel für diese Definition ist in Ihrem Wörterbuch möglicherweise nicht vorhanden.

Jetzt werden wir unter die Haube schauen. Wenn Sie ein Wörterbuch erstellen, reserviert Ihr Compiler eine Reservierung für den Bucket (Leerzeichen im Speicher, um Ihre Datensätze zu speichern). Bucket speichert Schlüssel nicht so, wie Sie sie definieren.Jeder Schlüssel wird gehackt, bevor er in den Bucket (definiert von Microsoft) geht. Erwähnenswert ist, dass dieser Wert unverändert bleibt.

Ich verwende den CRC32-Hashing-Algorithmus, um mein Beispiel zu vereinfachen. Wenn Sie definieren:

myDietFavorites[0] = "Pizza"; 

Was ist mit dem Eimer geht ist db2dc565 "Pizza" (vereinfacht).

Wenn Sie den Wert ändern mit:

myDietFavorites[0] = "Spaghetti"; 

Sie hash Ihre 0 die wiederum db2dc565 dann schauen Sie diesen Wert in dem Eimer bis zu finden, wenn es da ist. Wenn es da ist, schreiben Sie einfach den Wert neu, der dem Schlüssel zugewiesen ist. Wenn es nicht da ist, werden Sie Ihren Wert in den Eimer legen.

Wenn Sie Funktion auf Ihrem Wörterbuch Aufruf hinzufügen:

myDietFavorite.Add(0, "Chocolate"); 

Sie hash Ihre 0 ist es Wert zu denen in den Eimer zu vergleichen. Sie können es in den Eimer setzen nur, wenn es nicht ist.

Es ist wichtig zu wissen, wie es funktioniert, vor allem, wenn Sie mit Dictionaries von String- oder char-Schlüsseln arbeiten. Es ist Groß- und Kleinschreibung wegen der Hashing. Also zum Beispiel "Name"! = "Name". Lassen Sie uns unsere CRC32 verwenden, um dies darzustellen.

Wert für „name“ ist: e04112b1 Wert für „Name“ ist: 1107fb5b

Verwandte Themen