234 votes

Pourquoi est-il plus rapide de vérifier si le dictionnaire contient la clé, plutôt que de prendre l'exception dans le cas où il ne l'est pas?

Imaginez code:

   // some class
   public class obj
   {
   ...
   }

   public static Dictionary<string, obj> dict = new Dictionary<string, obj>();

   public static obj FromDict1(string name)
   {
       if (dict.ContainsKey(name))
       {
           return dict[name];
       }
       return null;
   }

   public static obj FromDict2(string name)
   {
       try
       {
           return dict[name];
       }
       catch (KeyNotFoundException)
       {
           return null;
       }
   }

J'étais curieux de savoir si il y a une différence dans les performances de ces 2 fonctions, parce que le premier DEVRAIT être plus LENTE que la seconde, étant donné qu'il est nécessaire de vérifier deux fois si le dictionnaire contient une valeur, tandis que la seconde fonction n'a besoin d'accéder au dictionnaire une seule fois, mais WOW, c'est en fait à l'opposé:

Boucle pour 1 000 000 valeurs (avec 100 000 et 900 000 non existant):

première fonction: 306 millisecondes

deuxième fonction: 20483 millisecondes

Pourquoi est-ce?

EDIT: Comme vous pouvez le constater dans les commentaires soufflet à cette question, la performance de la deuxième fonction est en fait légèrement mieux que la première dans le cas où il y a 0 non existant clés. Mais une fois qu'il y a au moins 1 ou plus non-existence de clés, la performance de la deuxième baisse rapidement.

401voto

Daniel Hilgarth Points 90722

D'une part, de lever des exceptions est intrinsèquement cher, parce que la pile doit être dénoué etc.
D'autre part, l'accès à une valeur dans un dictionnaire par sa clé n'est pas cher, parce que c'est un rapide, O(1).

BTW: La bonne façon de le faire est d'utiliser TryGetValue

obj item;
if(!dict.TryGetValue(name, out item))
    return null;
return item;

Ceci permet d'accéder au dictionnaire qu'une seule fois au lieu de deux fois.
Si vous voulez vraiment tout retour null si la clé n'existe pas, le code ci-dessus peut être simplifiée en outre:

obj item;
dict.TryGetValue(name, out item);
return item;

Cela fonctionne, car TryGetValue jeux item de null si pas de clé avec name existe.

6voto

Ed Hermanson Points 61

Les dictionnaires sont spécifiquement conçus pour faire super rapide touche de recherches. Ils sont mis en œuvre comme les tables de hashage et le plus d'entrées le plus vite ils sont par rapport à d'autres méthodes. En utilisant l'exception du moteur est supposé être fait lors de votre méthode a échoué à faire ce que vous l'avez conçu à faire, car c'est un grand ensemble d'objet qui vous donne beaucoup de fonctionnalités pour la gestion des erreurs. J'ai construit toute une bibliothèque de classe une fois avec tout entouré par des blocs try catch fois et a été consterné de voir la sortie de débogage qui contenait une autre ligne pour chaque unique de plus de 600 exceptions!

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X