Recuperación de las mejores prácticas de valor de diccionario

79

Recientemente me di cuenta Dictionary.TryGetValue(TKey key, out TValue value)y tenía curiosidad sobre cuál es el mejor método para recuperar un valor del Diccionario.

Tradicionalmente he hecho:

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

a menos que sepa que tiene que estar ahí.

¿Es mejor simplemente hacer:

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

¿Cuál es la mejor práctica? ¿Es uno más rápido que el otro? Me imagino que la versión de prueba sería más lenta ya que se 'traga' un intento / captura dentro de sí mismo y lo usa como lógica, ¿no?

Nicolás Mancuso
fuente

Respuestas:

84

TryGetValue es un poco más rápido, porque FindEntry solo se llamará una vez.

¿Cuanto más rápido? Depende del conjunto de datos a mano. Cuando llama al método Contains, Dictionary realiza una búsqueda interna para encontrar su índice. Si devuelve verdadero, necesita otra búsqueda de índice para obtener el valor real. Cuando usa TryGetValue, busca el índice solo una vez y, si lo encuentra, asigna el valor a su variable.

FYI: En realidad, no está detectando un error.

Está llamando:

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;
}

ContainsKey es esta:

public bool ContainsKey(TKey key)
{
    return (this.FindEntry(key) >= 0);
}
Miqueas
fuente
TryGetValue es un poco más rápido, porque FindEntry solo se llamará una vez.
Joe
1
TryGetValue es mucho más rápido cuando tienes un diccionario grande
Diadistis
4
Teóricamente (bueno, también en la práctica), esto no debería depender del tamaño del diccionario, ya que el tiempo esperado (!) De recuperación es constante, es decir, ¡independiente del tamaño del diccionario!
Konrad Rudolph
29

Bueno, de hecho, TryGetValue es más rápido. ¿Cuanto más rápido? Depende del conjunto de datos a mano. Cuando llama al método Contains, Dictionary realiza una búsqueda interna para encontrar su índice. Si devuelve verdadero, necesita otra búsqueda de índice para obtener el valor real. Cuando usa TryGetValue, busca el índice solo una vez y, si lo encuentra, asigna el valor a su variable.

Editar:

Ok, entiendo tu confusión, así que déjame explicarte:

Caso 1:

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

En este caso, hay 2 llamadas a FindEntry, una para verificar si la clave existe y otra para recuperarla.

Caso 2:

myDict.TryGetValue(somekey, out someVal)

En este caso, solo hay una llamada a FindKey porque el índice resultante se mantiene para la recuperación real en el mismo método.

Diadistis
fuente
Convenido. TryGetValue elimina la necesidad de realizar la búsqueda de claves dos veces. También puede ayudar en el caso de subprocesos múltiples. Entre el momento en que verifica si el valor existe, es posible que se haya agregado o eliminado. Esto puede provocar excepciones de "clave ya existente" o "clave no encontrada".
Brian Rudolph
0

Me imagino que trygetvalue está haciendo algo más como:

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

Así que, con suerte, no hay intento / captura en ningún lado.

Creo que en realidad es solo un método de conveniencia. Generalmente lo uso porque guarda una o dos líneas de código.

Jennifer
fuente