Ik kwam onlangs dit antwoord op StackOverflow tegen en wilde er wat aandacht aan besteden (nadruk van mij):
Dit probleem manifesteerde zich tijdens het debuggen toen ik een horloge had dat probeerde het item van de "ontbrekende" sleutel terug te geven . Eigenlijk had verder gefrustreerd debuggen hetzelfde probleem toen ik letterlijk een horloge had voor de [scriptingdictonaryObject].exists() voorwaardelijk); Ik stel voor dat de "ontbrekende" sleutel wordt toegevoegd vanwege het horloge . Toen ik het horloge verwijderde en in plaats daarvan een tijdelijk werkblad maakte om de array naar te kopiëren tijdens het hardlopen, werden de ongewenste sleutels niet langer toegevoegd.Woordenboekobject dat items toevoegt voordat .add() wordt aangeroepen Ik gebruik een woordenboekobject uit de MS Scripting Runtime-bibliotheek om een reeks arrays op te slaan en zo nodig bewerkingen uit te voeren op de arraycellen. Er is een for-lus om het proces te doorlopen... Stack Overflowriddley_w
Wat is hier aan de hand?
Een van de "kenmerken" van een Dictionary-object is dat het impliciet nieuwe items maken zonder de .Add-methode expliciet te hoeven aanroepen . Wat is het verschil tussen impliciet en expliciet?
Opmerking:vroeg gebruik van het Dictionary-object vereist een verwijzing naar de "Microsoft Scripting Runtime" (details hier).
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")
Hier is het relevante deel van de documentatie met betrekking tot impliciete sleutel maken:
Opmerkingen
Als toets wordt niet gevonden bij het wijzigen van een item , een nieuwe sleutel is gemaakt met het opgegeven nieuwe item . Als toets wordt niet gevonden bij een poging om een bestaand item te retourneren, een nieuwe sleutel is gemaakt en het bijbehorende item wordt leeg gelaten.
Het probleem reproduceren
Laten we het probleem reproduceren om precies te zien waar de dingen zijwaarts gaan.
Verwacht gedrag
Maak de volgende voorbeeldroutine:
Sub WatchOut()
Dim MyDict As Dictionary
Set MyDict = New Dictionary
Debug.Print "KeyA exists? "; MyDict.Exists("KeyA")
End Sub
Voer de bovenstaande routine uit vanuit het directe venster en het zou False moeten retourneren:
WatchOut
KeyA exists? False
Een horloge toevoegen
Laten we nu een horloge van het item "KeyA" toevoegen:
Laten we proberen de WatchOut . uit te voeren weer routine:
WatchOut
KeyA exists? False
Tot nu toe, zo goed. Misschien is dit toch geen probleem.
Stap door de code
Laten we een Stop . toevoegen statement om de code te forceren om te breken:
Sub WatchOut()
Dim MyDict As Dictionary
Set MyDict = New Dictionary
Stop
Debug.Print "KeyA exists? "; MyDict.Exists("KeyA")
End Sub
Laten we nu proberen de WatchOut . uit te voeren routine:
WatchOut
KeyA exists? True
Aha! De combinatie van het horloge en het inbreken in de debugger is voldoende om de "bug" te laten verschijnen. Ik plaats bug tussen schrikaanhalingstekens omdat het eigenlijk verwacht gedrag is voor de debugger. Maar het is vrijwel zeker onverwacht gedrag voor de ontwikkelaar.
(Merk op dat er niets bijzonders is aan de Stop commando dat dit gedrag veroorzaakt. U kunt de Stop . verwijderen regel en stel een breekpunt in op de code en hetzelfde gedrag zal optreden.)
Je kunt zien waar dit soort dingen ervoor kunnen zorgen dat je je haar uittrekt tijdens het debuggen. Elke keer dat het gedrag van je programma anders is tijdens normaal draaien dan tijdens het debuggen, heb je de ingrediënten voor een vervelende debugging-sessie.
Samenvatting
Stappen om het probleem te reproduceren:
- Een horloge maken voor een specifiek woordenboekitem
- Breek in in de debugger tijdens het uitvoeren van de code
Dit zal waarschijnlijk maar één of twee ontwikkelaars helpen. Maar het zal die ontwikkelaars mogelijk uren besparen van frustratie. En als ik eerlijk ben, ben ik net zo waarschijnlijk een van die ontwikkelaars;-).