Imagina el código:
public class obj
{
// elided
}
public static Dictionary<string, obj> dict = new Dictionary<string, obj>();
Método 1
public static obj FromDict1(string name)
{
if (dict.ContainsKey(name))
{
return dict[name];
}
return null;
}
Método 2
public static obj FromDict2(string name)
{
try
{
return dict[name];
}
catch (KeyNotFoundException)
{
return null;
}
}
Tenía curiosidad por saber si hay una diferencia en el rendimiento de estas 2 funciones, porque la primera DEBE ser MÁS LENTA que la segunda, dado que debe verificar dos veces si el diccionario contiene un valor, mientras que la segunda función solo necesita acceder al diccionario una vez pero GUAU, en realidad es lo contrario:
Bucle para 1 000 000 valores (con 100 000 existentes y 900 000 no existentes):
primera función: 306 milisegundos
segunda función: 20483 milisegundos
¿Porqué es eso?
EDITAR: Como puede observar en los comentarios debajo de esta pregunta, el rendimiento de la segunda función es en realidad ligeramente mejor que la primera en caso de que haya 0 teclas no existentes. Pero una vez que hay al menos 1 o más claves no existentes, el rendimiento de la segunda disminuye rápidamente.
fuente
ContainsKey
se esperaO(1)
...O(1)
en la búsqueda en el diccionario ... Especialmente porque hacer dosO(1)
operaciones sigue siendo asintóticamenteO(1)
.Respuestas:
Por un lado, lanzar excepciones es inherentemente costoso , porque la pila tiene que ser desenrollada, etc.
Por otro lado, acceder a un valor en un diccionario por su clave es barato, porque es una operación rápida, O (1).
Por cierto: la forma correcta de hacer esto es usar
TryGetValue
Esto accede al diccionario solo una vez en lugar de dos veces.
Si realmente desea regresar solo
null
si la clave no existe, el código anterior se puede simplificar aún más:Esto funciona, porque se
TryGetValue
estableceitem
ennull
si noname
existe una clave con .fuente
Los diccionarios están diseñados específicamente para realizar búsquedas de teclas súper rápidas. Se implementan como tablas hash y cuantas más entradas, más rápido son en relación con otros métodos. Se supone que el uso del motor de excepción solo se debe hacer cuando su método no ha podido hacer lo que usted diseñó porque es un gran conjunto de objetos que le brinda mucha funcionalidad para manejar errores. ¡Construí una clase de biblioteca completa una vez con todo rodeado de bloques de prueba una vez y me horroricé al ver la salida de depuración que contenía una línea separada para cada una de las más de 600 excepciones!
fuente