Verschiedene Möglichkeiten zum Hinzufügen zum Wörterbuch

107

Was ist der Unterschied in Dictionary.add(key, value)und Dictionary[key] = value?

Ich habe festgestellt, dass die letzte Version ArgumentExceptionbeim Einfügen eines doppelten Schlüssels kein löst , aber gibt es einen Grund, die erste Version zu bevorzugen?

Bearbeiten : Hat jemand eine maßgebliche Informationsquelle dazu? Ich habe MSDN ausprobiert, aber es ist wie immer eine wilde Gänsejagd :(

Sune Rievers
quelle

Antworten:

109

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

Dies ist der This-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 nicht die gesamte Insert-Methode veröffentlichen, da sie ziemlich lang ist. Die Methodendeklaration lautet jedoch wie folgt:

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

Und weiter unten in der Funktion passiert Folgendes:

if ((this.entries[i].hashCode == num) && this.comparer.Equals(this.entries[i].key, key))
{
    if (add)
    {
        ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_AddingDuplicate);
    }

Womit überprüft wird, ob der Schlüssel bereits vorhanden ist, und wenn dies der Fall ist und der Parameter add wahr ist, wird die Ausnahme ausgelöst.

Die Leistung ist also in jeder Hinsicht gleich.

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

Entschuldigung für den langen Beitrag, ich hoffe es ist okay.

Steffen
quelle
+1 Sehr interessant, danke für deinen Beitrag! Es scheint, dass die Leistung hier fast identisch ist, wie die anderen Poster angedeutet haben, jedenfalls ein großartiger Fund :)
Sune Rievers
70

Die erste Version fügt dem Wörterbuch ein neues KeyValuePair hinzu, das ausgelöst wird, wenn der Schlüssel bereits im Wörterbuch enthalten ist. Der zweite, der den Indexer verwendet, fügt ein neues Paar hinzu, wenn der Schlüssel nicht vorhanden ist, überschreibt jedoch den Wert des Schlüssels, wenn er bereits im Wörterbuch vorhanden ist.

IDictionary<string, string> strings = new Dictionary<string, string>();

strings["foo"] = "bar";          //strings["foo"] == "bar"
strings["foo"] = string.Empty;   //strings["foo"] == string.empty
strings.Add("foo", "bar");       //throws     
hhravn
quelle
+1 Haben Sie eine Quelle für die oben genannten Informationen? Ich bin daran interessiert zu erfahren, ob die Verwendung der ersten oder letzteren Form Nebenwirkungen oder Einschränkungen aufweist.
Sune Rievers
3
Ich habe nicht wirklich eine Quelle als solche, aber ich denke nicht, dass viel mehr dahinter steckt, 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 verwendet wird.
Hhravn
1
Die akzeptierte Antwort auf Steffens wurde geändert, da seine Dokumentation erstklassig ist. Dies ist jedoch immer noch eine gute Antwort.
Sune Rievers
@Sune: Schlechter Zug ... persönlich denke ich, dass diese Antwort Steffen's voraus ist ... direkt auf den Punkt und ein anständiges Beispiel.
Demoncodemonkey
1
@SuneRievers Ich denke, es wird mehr Helphul für Menschen sein, wenn eine akzeptierte Antwort dafür anstelle der aktuell akzeptierten Antwort. Da dies genau die Frage beantwortet ("Was ist der Unterschied") und nicht die akzeptierte Frage (die über Leistung spricht und fast 99% der Benutzer, die dieses Thema suchen (wie ich), den "Unterschied" benötigt (warum habe ich das getroffen?) Thema), und akzeptierte Antwort war für mich nutzlos und verschwendet unsere zweite. Stattdessen ist diese Antwort genau.
T.Todua
30

Dictionary.Add(key, value)und Dictionary[key] = valuehaben verschiedene Zwecke:

  • Verwenden Sie die AddMethode, um ein neues Schlüssel / Wert-Paar hinzuzufügen. Vorhandene Schlüssel werden nicht ersetzt (anArgumentException wird geworfen).
  • Verwenden Sie den Indexer, wenn Sie sich nicht darum kümmern, ob der Schlüssel bereits im Wörterbuch vorhanden ist. Mit anderen Worten: Fügen Sie das Schlüssel / Wert-Paar hinzu, wenn sich der Schlüssel nicht im Wörterbuch befindet, oder ersetzen Sie den Wert für den angegebenen Schlüssel, wenn der Schlüssel bereits vorhanden ist im Wörterbuch.
Michael Damatov
quelle
1
Code, der die Absicht selbst beschreibt, ist wichtig und immens wertvoll (und erfordert wenig bis gar keine Kommentare). Diese Antwort zeigt den Unterschied in der Absicht bei beiden Methoden und sollte bei der Auswahl einer Methode befolgt werden. Mit anderen Worten, verwenden Sie das 'Indexer-Hinzufügen' nicht, wenn Sie im Voraus wissen, dass Sie immer hinzufügen werden oder sogar immer hinzufügen müssen. Das Auslösen einer IndexOutOfBounds-Ausnahme ist besser als unerwartetes Verhalten.
Ryancdotnet
28

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

Dictionaryist die Liste, in der KeyValuePair<Tkey, Tvalue>jeder Wert durch seinen eindeutigen Schlüssel dargestellt wird. Angenommen, wir haben eine Liste Ihrer Lieblingsspeisen. Jeder Wert (Name des Lebensmittels) wird durch seinen eindeutigen Schlüssel dargestellt (eine Position = wie sehr Sie dieses Lebensmittel mögen).

Beispielcode:

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

Nehmen wir an, Sie möchten gesund bleiben, Ihre Meinung geändert haben und Ihren Lieblings-Burger durch Salat ersetzen. Ihre Liste ist immer noch eine Liste Ihrer Favoriten. Sie werden die Art der Liste nicht ändern. Ihr Favorit bleibt die Nummer eins auf der Liste, nur der Wert ändert sich. Dies ist, wenn Sie dies nennen:

/*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, dass Sie der Programmierer sind, und von nun an beenden Sie Ihre Sätze mit; Sie lehnen die Verwendung von Emojis ab, da diese einen Kompilierungsfehler auslösen würden und die Liste aller Favoriten auf dem Index 0 basiert.

Ihre Ernährung hat sich ebenfalls geändert! Also ändern Sie Ihre Liste erneut:

/*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");

Beim Definieren gibt es zwei Möglichkeiten: Sie möchten entweder eine neue Definition für etwas geben, das vorher nicht vorhanden war, oder Sie möchten die bereits vorhandene Definition ändern.

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

Jetzt schauen wir unter die Haube. Wenn Sie ein Wörterbuch erstellen, reserviert Ihr Compiler den Bucket (Speicherplätze im Speicher zum Speichern Ihrer Datensätze). Bucket speichert Schlüssel nicht so, wie Sie sie definieren. Jeder Schlüssel wird gehasht, bevor er in den von Microsoft definierten Bucket wechselt. Erwähnenswert ist, dass der Wertteil unverändert bleibt.

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

myDietFavorites[0] = "Pizza";

Was in den Eimer geht, ist db2dc565 "Pizza" (vereinfacht).

Wenn Sie den Wert ändern mit:

myDietFavorites[0] = "Spaghetti";

Wenn Sie Ihre 0 hashen, die wieder db2dc565 ist, suchen Sie diesen Wert in Ihrem Bucket, um festzustellen, ob er vorhanden ist. Wenn es dort ist, schreiben Sie einfach den dem Schlüssel zugewiesenen Wert neu. Wenn es nicht da ist, legen Sie Ihren Wert in den Eimer.

Wenn Sie die Funktion Hinzufügen in Ihrem Wörterbuch aufrufen, wie folgt:

myDietFavorite.Add(0, "Chocolate");

Sie haben Ihre 0 gehasht, um den Wert mit denen im Bucket zu vergleichen. Sie dürfen es nur in den Eimer legen, wenn es nicht da ist .

Es ist wichtig zu wissen, wie es funktioniert, insbesondere wenn Sie mit Wörterbüchern vom Typ string oder char arbeiten. Bei Hashing wird zwischen Groß- und Kleinschreibung unterschieden. Also zum Beispiel "Name"! = "Name". Verwenden wir unseren CRC32, um dies darzustellen.

Wert für "Name" ist: e04112b1 Wert für "Name" ist: 1107fb5b

Kamil Kurzynowski
quelle
Diese zwei Zeilen reichen aus, um zu verstehen ....... Es gibt zwei Möglichkeiten beim Definieren: Sie möchten entweder eine neue Definition für etwas geben, das vorher nicht existiert, oder Sie möchten die Definition ändern, die bereits existiert. Mit der Methode Hinzufügen können Sie einen Datensatz hinzufügen, jedoch nur unter einer Bedingung: Der Schlüssel für diese Definition ist möglicherweise nicht in Ihrem Wörterbuch vorhanden.
Niraj Trivedi
4

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

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

Guffa
quelle
0

Verwenden Sie angesichts der wahrscheinlichsten Ähnlichkeiten in der Leistung alles, was sich für den von Ihnen verwendeten Code korrekter und lesbarer anfühlt.

Ich bin der Meinung, dass eine Operation, die eine Addition beschreibt, da das Vorhandensein des Schlüssels bereits eine wirklich seltene Ausnahme darstellt, am besten mit der Addition dargestellt wird. Semantisch macht es mehr Sinn.

Das dict[key] = valuestellt besser eine Substitution dar. Wenn ich diesen Code sehe, erwarte ich zur Hälfte, dass der Schlüssel sowieso schon im Wörterbuch ist.

Jorge Córdoba
quelle
Ich würde annehmen, dass es einen kleinen Leistungsgewinn gibt, wenn nicht geprüft wird, ob der Schlüssel zuerst vorhanden ist. Ich würde nicht erwarten, dic[key] = valuedass der Schlüssel bereits vorhanden war, aber ich denke, das ist umstritten;)
Sune Rievers
2
+ Ich denke, das Werfen sollte niemals dazu verwendet werden, zu überprüfen, ob der Schlüssel bereits dargestellt ist. if (! strings.ContainsKey ("foo")) strings.Add ("foo", "bar");
Hhravn
0

Einer weist einen Wert zu, während der andere dem Wörterbuch einen neuen Schlüssel und Wert hinzufügt.

Joshua Smith
quelle
0

So fügen Sie den Wert in das Wörterbuch ein

 Dictionary<string, string> dDS1 = new Dictionary<string, string>();//Declaration
 dDS1.Add("VEqpt", "aaaa");//adding key and value into the dictionary
 string Count = dDS1["VEqpt"];//assigning the value of dictionary key to Count variable
 dDS1["VEqpt"] = Count + "bbbb";//assigning the value to key
Maghalakshmi Saravana
quelle