3

Recently I've encountered a rather odd dictionary behaviour.

Sub DictTest()
    Dim iDict As Object
    Dim i As Integer
    Dim strArr() As String
    Set iDict = CreateObject("Scripting.Dictionary")
    strArr = Split("Why does this happen ? Why does this happen over and over ?", " ")
    For i = LBound(strArr) To UBound(strArr)
        iDict(strArr(i)) = strArr(i)
    Next
End Sub

The output is iDict populated with 7 items: Taken from locals window But whenever I add watch:
Add Watch window
It adds an empty item to a dictionary:
Taken from watch window
Why does adding a watch expression create an empty item in the dictionary?

AntiDrondert
  • 1,128
  • 8
  • 21

1 Answers1

5

If you examine the entry in the dictionary with a key of "What???" then naturally an entry must be created in the dictionary in order to show you that entry.

If you want to just check whether an entry exists, then perform a watch on iDict.Exists("What???").

Adding watch Watch Window

Adding a watch is operating no differently to the following code:

Sub DictTest()
    Dim iDict As Object
    Dim i As Integer
    Dim strArr() As String
    Set iDict = CreateObject("Scripting.Dictionary")
    strArr = Split("Why does this happen ? Why does this happen over and over ?", " ")
    For i = LBound(strArr) To UBound(strArr)
        iDict(strArr(i)) = strArr(i)
    Next
    MsgBox "The value of the 'What???' entry in iDict is '" & iDict("What???") & "'"
End Sub

This changing of the contents of a Dictionary object is no different to using the Watch Window to change the value of x in the following situation:

enter image description here

In the above code, I used the watch window to edit the value of x from 5 to 10 prior to the Debug.Print statement.

YowE3K
  • 23,852
  • 7
  • 26
  • 40
  • How does looking add an entry? I mean, if I check for non-existing *j*, it won't initialize empty variant *j* variable. Or if I check for *strArr(13)*, it won't show empty 13-th item, it will throw *Subscript out of range* error. – AntiDrondert Jan 25 '18 at 07:57
  • @AntiDrondert I thought you were talking about dictionaries, not arrays. And checking for non-existing on a dictionary won't create an entry, that's why you should do that in the Watch Window, if you are wanting to see whether an entry exists. – YowE3K Jan 25 '18 at 08:00
  • I'm trying to draw a parallel, because I can't explain what I mean any other way, the question is still about dictionaries. What I thought is Watch expressions can't affect existing objects and it's only purpose to check for values. – AntiDrondert Jan 25 '18 at 08:03
  • Adding watch expression essentialy executes code similiar to an expression in given context, that is the reason of new entry, do I understand it correctly? – AntiDrondert Jan 25 '18 at 08:40
  • @AntiDrondert The Watch Window can change variables. I just updated the answer to include a simple example showing a change to an `Integer` variable. Adding an entry to your `iDict` object is similarly possible via the Watch Window. It's just normal behaviour caused by the Watch Window permitting changes to variables. – YowE3K Jan 25 '18 at 09:04
  • 1
    It's because of how Dictionary is implemented. The Item property (which is the default property and thus called when `iDict("a")` is executed) will add the key even in the Property Get case (not just the Property Let case as you might expect). The Watch Window isn't the cause here - it just calls Property Get. The seemingly unusual implementation of Dictionary is the reason. – andrew Jan 25 '18 at 09:11
  • 1
    @andrew So basicaly it happens not because of watch expressions, but of dictionary Get Prp[erty? – AntiDrondert Jan 25 '18 at 09:15
  • @AntiDrondert Yes, it's exactly like the extra line I added to your code. Even though the item doesn't exist, it adds it, then gets it. – YowE3K Jan 25 '18 at 09:16
  • @andrew Thanks to both of you for explicit explanation. – AntiDrondert Jan 25 '18 at 09:26