Best Practices für Wörterbuchwerte abrufen

79

Ich habe es erst kürzlich bemerkt Dictionary.TryGetValue(TKey key, out TValue value)und war neugierig, welcher Ansatz besser ist, um einen Wert aus dem Wörterbuch abzurufen.

Ich habe traditionell getan:

if (myDict.Contains(someKey))
     someVal = myDict[someKey];
     ...

es sei denn , ich weiß , es hat dort zu sein.

Ist es besser, einfach zu tun:

if (myDict.TryGetValue(somekey, out someVal)
    ...

Welches ist die bessere Praxis? Ist einer schneller als der andere? Ich würde mir vorstellen, dass die Try-Version langsamer ist, da sie einen Try / Catch in sich "verschluckt" und dies als Logik verwendet, nicht wahr?

Nicholas Mancuso
quelle

Antworten:

84

TryGetValue ist etwas schneller, da FindEntry nur einmal aufgerufen wird.

Wie viel schneller? Dies hängt vom jeweiligen Datensatz ab. Wenn Sie die Contains-Methode aufrufen, führt Dictionary eine interne Suche durch, um den Index zu finden. Wenn true zurückgegeben wird, benötigen Sie eine weitere Indexsuche, um den tatsächlichen Wert zu erhalten. Wenn Sie TryGetValue verwenden, wird nur einmal nach dem Index gesucht, und wenn er gefunden wird, weist er Ihrer Variablen den Wert zu.

Zu Ihrer Information: Es ist eigentlich kein Fehler.

Es ruft:

public bool TryGetValue(TKey key, out TValue value)
{
    int index = this.FindEntry(key);
    if (index >= 0)
    {
        value = this.entries[index].value;
        return true;
    }
    value = default(TValue);
    return false;
}

Enthält Schlüssel ist dies:

public bool ContainsKey(TKey key)
{
    return (this.FindEntry(key) >= 0);
}
Micah
quelle
TryGetValue ist etwas schneller, da FindEntry nur einmal aufgerufen wird.
Joe
1
TryGetValue ist viel schneller, wenn Sie ein großes Wörterbuch haben
Diadistis
4
Theoretisch (auch in der Praxis) sollte dies nicht von der Größe des Wörterbuchs abhängen, da die erwartete (!) Abrufzeit konstant ist, dh unabhängig von der Wörterbuchgröße!
Konrad Rudolph
29

Tatsächlich ist TryGetValue schneller. Wie viel schneller? Dies hängt vom jeweiligen Datensatz ab. Wenn Sie die Contains-Methode aufrufen, führt Dictionary eine interne Suche durch, um den Index zu finden. Wenn true zurückgegeben wird, benötigen Sie eine weitere Indexsuche, um den tatsächlichen Wert zu erhalten. Wenn Sie TryGetValue verwenden, wird nur einmal nach dem Index gesucht, und wenn er gefunden wird, weist er Ihrer Variablen den Wert zu.

Bearbeiten:

Ok, ich verstehe Ihre Verwirrung, also lassen Sie mich näher darauf eingehen:

Fall 1:

if (myDict.Contains(someKey))
     someVal = myDict[someKey];

In diesem Fall gibt es zwei Aufrufe von FindEntry, einen, um zu überprüfen, ob der Schlüssel vorhanden ist, und einen, um ihn abzurufen

Fall 2:

myDict.TryGetValue(somekey, out someVal)

In diesem Fall wird FindKey nur einmal aufgerufen, da der resultierende Index für den tatsächlichen Abruf in derselben Methode beibehalten wird.

Diadistis
quelle
Einverstanden. TryGetValue macht die zweimalige Suche nach Schlüsseln überflüssig. Dies kann auch beim Multithreading hilfreich sein. Zwischen dem Zeitpunkt, an dem Sie prüfen, ob der Wert vorhanden ist, wurde er möglicherweise hinzugefügt oder entfernt. Dies kann dazu führen, dass Ausnahmen "Schlüssel existiert bereits" oder "Schlüssel nicht gefunden" auftreten.
Brian Rudolph
0

Ich stelle mir vor, dass trygetvalue eher so etwas macht wie:

if(myDict.ReallyOptimisedVersionofContains(someKey))
{ 
  someVal = myDict[someKey];
  return true;
}
return false;

Also hoffentlich nirgendwo versuchen / fangen.

Ich denke, es ist wirklich nur eine Methode der Bequemlichkeit. Ich benutze es im Allgemeinen, da es eine oder zwei Codezeilen speichert.

Jennifer
quelle