Imaginez le code:
public class obj
{
// elided
}
public static Dictionary<string, obj> dict = new Dictionary<string, obj>();
Méthode 1
public static obj FromDict1(string name)
{
if (dict.ContainsKey(name))
{
return dict[name];
}
return null;
}
Méthode 2
public static obj FromDict2(string name)
{
try
{
return dict[name];
}
catch (KeyNotFoundException)
{
return null;
}
}
J'étais curieux de savoir s'il y avait une différence dans les performances de ces 2 fonctions, car la première DEVRAIT être plus LENTE que la seconde - étant donné qu'elle doit vérifier deux fois si le dictionnaire contient une valeur, tandis que la deuxième fonction n'a besoin d'accéder qu'au dictionnaire uniquement une fois mais WOW, c'est en fait l'opposé:
Boucle pour 1 000 000 de valeurs (avec 100 000 existantes et 900 000 non existantes):
première fonction: 306 millisecondes
deuxième fonction: 20483 millisecondes
Pourquoi donc?
EDIT: Comme vous pouvez le remarquer dans les commentaires ci-dessous cette question, les performances de la deuxième fonction sont en fait légèrement meilleures que la première dans le cas où il n'y a 0 clé non existante. Mais une fois qu'il y a au moins 1 ou plusieurs clés non existantes, les performances de la seconde diminuent rapidement.
la source
ContainsKey
c'est prévuO(1)
...O(1)
recherche dans le dictionnaire ... D'autant plus que faire deuxO(1)
opérations est toujours asymptotiqueO(1)
.Réponses:
D'une part, lever des exceptions est intrinsèquement coûteux , car la pile doit être déroulée, etc.
D'un autre côté, accéder à une valeur dans un dictionnaire par sa clé est bon marché, car il s'agit d'une opération O (1) rapide.
BTW: La bonne façon de procéder consiste à utiliser
TryGetValue
Cela accède au dictionnaire une seule fois au lieu de deux.
Si vous voulez vraiment retourner
null
si la clé n'existe pas, le code ci-dessus peut être simplifié davantage:Cela fonctionne, parce que les
TryGetValue
ensemblesitem
ànull
si aucune clé avecname
existe.la source
Les dictionnaires sont spécialement conçus pour effectuer des recherches de touches ultra rapides. Ils sont implémentés sous forme de tables de hachage et plus il y a d'entrées, plus ils sont rapides par rapport aux autres méthodes. L'utilisation du moteur d'exception n'est censée être effectuée que lorsque votre méthode n'a pas réussi à faire ce que vous avez conçu, car il s'agit d'un grand ensemble d'objets qui vous offrent de nombreuses fonctionnalités pour gérer les erreurs. J'ai construit une classe de bibliothèque entière une fois avec tout entouré de blocs catch catch une fois et j'ai été consterné de voir la sortie de débogage qui contenait une ligne distincte pour chacune des 600 exceptions!
la source