sql >> Databasteknik >  >> RDS >> Access

Var försiktig med vad du tittar efter

Jag stötte på det här svaret på StackOverflow häromdagen och ville uppmärksamma det lite (min betoning):

Det här problemet visade sig under felsökningen när jag hade en klocka som försökte returnera den "saknade" nyckelns objekt . I själva verket hade ytterligare frustrerad felsökning samma problem när jag bokstavligen hade koll på [scriptingdictonaryObject].exists() condtional); Jag föreslår att den "saknade" nyckeln läggs till på grund av klockan . När jag tog bort klockan och istället skapade ett tillfälligt kalkylblad att kopiera arrayen till medan jag körde lades de oönskade nycklarna inte längre till.
Ordboksobjekt som lägger till objekt före .add() kallas Jag använder ett ordboksobjekt från MS Scripting Runtime-biblioteket för att lagra en serie arrayer och utföra operationer på arraycellerna vid behov. Det finns en for-loop för att gå igenom processen... Stack Overflowriddley_w

Vad händer här?

En av "funktionerna" hos ett ordboksobjekt är att det kommer implicit skapa nya objekt utan att behöva anropa .Add-metoden explicit . Vad är skillnaden mellan implicit och explicit?

Obs! Tidig användning av Dictionary-objektet kräver en referens till "Microsoft Scripting Runtime" (detaljer här).

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")

Här är den relevanta delen av dokumentationen angående implicit nyckelskapande:

Anmärkningar
Om nyckel hittas inte när du ändrar ett objekt , en ny nyckel skapas med det angivna newitem . Om nyckel hittas inte när man försöker returnera en befintlig vara, en ny nyckel skapas och dess motsvarande objekt lämnas tomt.

Återskapa problemet

Låt oss reproducera problemet för att se exakt var saker går åt sidan.

Förväntat beteende

Skapa följande exempelrutin:

Sub WatchOut()
    Dim MyDict As Dictionary
    Set MyDict = New Dictionary
    
    Debug.Print "KeyA exists? "; MyDict.Exists("KeyA")
End Sub

Kör ovanstående rutin från det omedelbara fönstret och den bör returnera False:

WatchOut
KeyA exists? False

Lägg till en klocka

Låt oss nu lägga till en bevakning av "KeyA"-objektet:

Låt oss prova att köra WatchOut rutin igen:

WatchOut
KeyA exists? False

Än så länge är allt bra. Kanske är detta inte ett problem trots allt.

Steg igenom koden

Låt oss lägga till ett Stopp uttalande för att tvinga koden att gå sönder:

Sub WatchOut()
    Dim MyDict As Dictionary
    Set MyDict = New Dictionary
    
    Stop
    Debug.Print "KeyA exists? "; MyDict.Exists("KeyA")
End Sub

Nu ska vi försöka köra WatchOut rutin:

WatchOut
KeyA exists? True

A ha! Kombinationen av klockan och inbrott i debuggern räcker för att tvinga "buggen" att dyka upp. Jag lägger bugg i skrämmande citattecken eftersom det faktiskt är förväntat beteende för felsökaren. Men det är nästan säkert ett oväntat beteende för utvecklaren.

(Observera att det inte finns något speciellt med Stopp kommando som orsakar detta beteende. Du kan ta bort Stopp linje och ställ in en brytpunkt på koden och samma beteende kommer att inträffa.)

Du kan se var den här typen av saker kan få dig att dra ut håret när du felsöker. Varje gång ditt programs beteende är annorlunda när det körs normalt jämfört med under felsökning, har du förutsättningarna för en försvårande felsökningssession.

Sammanfattning

Steg för att återskapa problemet:

  1. Skapa en klocka för ett specifikt ordboksobjekt
  2. Tryck in i felsökaren medan du kör koden

Detta kommer förmodligen bara att hjälpa en eller två utvecklare. Men det kommer potentiellt att spara dessa utvecklare timmar av frustration. Och om jag ska vara ärlig så är jag lika sannolikt som någon annan att vara en av dessa utvecklare;-).


  1. SQL mindre än () operatör för nybörjare

  2. Anropa en lagrad procedur inom en lagrad procedur

  3. Om du använder indexerade vyer och MERGE, läs detta!

  4. Hantera MDF-filer i SQL Server 2019