Je suis tombé sur cette réponse sur StackOverflow l'autre jour et je voulais y attirer l'attention (c'est moi qui souligne):
Ce problème s'est manifesté lors du débogage lorsque j'avais une montre qui tentait de renvoyer l'élément de la clé "manquante" . En fait, un débogage plus frustré a eu le même problème lorsque j'ai littéralement surveillé le [scriptingdictonaryObject].exists() condtional); Je suggère que la clé "manquante" soit ajoutée à cause de la montre . Lorsque j'ai supprimé la montre et créé à la place une feuille de calcul temporaire pour copier le tableau pendant l'exécution, les clés indésirables n'ont plus été ajoutées.Objet dictionnaire ajoutant des éléments avant que .add() soit appeléJ'utilise un objet dictionnaire de la bibliothèque MS Scripting Runtime pour stocker une série de tableaux et effectuer des opérations sur les cellules du tableau si nécessaire. Il y a une boucle for pour parcourir le processus... Stack Overflowriddley_w
Que se passe-t-il ici ?
L'une des "caractéristiques" d'un objet Dictionary est qu'il sera implicitement créer de nouveaux éléments sans avoir besoin d'appeler la méthode .Add explicitement . Quelle est la différence entre implicite et explicite ?
Remarque :L'utilisation anticipée de l'objet Dictionary nécessite une référence au "Microsoft Scripting Runtime" (détails ici).
Dim MyDict As New Dictionary
'Explicit add
MyDict.Add "KeyA", "Item A"
'Implicit add
MyDict.Item("KeyB") = "Item B"
Debug.Print MyDict("KeyA"); vbNewLine; MyDict("KeyB")
Voici la partie pertinente de la documentation concernant implicite création de clé :
Remarques
Si clé n'est pas trouvé lors de la modification d'un élément , une nouvelle clé est créé avec le newitem spécifié . Si clé n'est pas trouvé lors de la tentative de retour d'un élément existant, une nouvelle clé est créé et son élément correspondant est laissé vide.
Reproduire le problème
Reproduisons le problème pour voir exactement où les choses tournent mal.
Comportement attendu
Créez l'exemple de routine suivant :
Sub WatchOut()
Dim MyDict As Dictionary
Set MyDict = New Dictionary
Debug.Print "KeyA exists? "; MyDict.Exists("KeyA")
End Sub
Exécutez la routine ci-dessus à partir de la fenêtre immédiate et elle devrait renvoyer False :
WatchOut
KeyA exists? False
Ajouter une montre
Maintenant, ajoutons une montre de l'élément "KeyA":
Essayons d'exécuter le WatchOut routine à nouveau :
WatchOut
KeyA exists? False
Jusqu'ici tout va bien. Peut-être que ce n'est pas un problème après tout.
Parcourir le code
Ajoutons un Stop déclaration pour forcer le code à casser :
Sub WatchOut()
Dim MyDict As Dictionary
Set MyDict = New Dictionary
Stop
Debug.Print "KeyA exists? "; MyDict.Exists("KeyA")
End Sub
Maintenant, essayons d'exécuter le WatchOut routine :
WatchOut
KeyA exists? True
Ah ! La combinaison de la montre et de l'effraction dans le débogueur suffit à forcer le "bug" à apparaître. J'ai mis bug entre guillemets effrayants, car il s'agit en fait du comportement attendu du débogueur. Mais c'est presque certainement un comportement inattendu pour le développeur.
(Notez qu'il n'y a rien de spécial à propos de l'Stop commande qui provoque ce comportement. Vous pouvez supprimer le Stop ligne et définissez un point d'arrêt sur le code et le même comportement se produira.)
Vous pouvez voir où ce genre de chose pourrait vous faire vous arracher les cheveux pendant le débogage. Chaque fois que le comportement de votre programme est différent lors de l'exécution normale par rapport au débogage, vous avez l'étoffe d'une session de débogage aggravante.
Résumé
Étapes pour reproduire le problème :
- Créer une surveillance pour un élément spécifique du dictionnaire
- Pénétrer dans le débogueur lors de l'exécution du code
Cela n'aidera probablement qu'un ou deux développeurs. Mais cela fera potentiellement gagner des heures à ces développeurs de frustration. Et, pour être honnête, je suis aussi susceptible que n'importe qui d'être l'un de ces développeurs ;-).