Link to home
Start Free TrialLog in
Avatar of Richard
RichardFlag for United States of America

asked on

VB6 using 2 dictionaries with same class

I have a Class Questions which includes the following properties:
1) The Question - String
2) The QuestCode - String
3) PAQuest - Boolean
4) QuestAns - Boolean
5) The QuestID - Long

I instance an object
     Set oQst = New clsQuestions
I load the object from an SQL datatable
I then add the object into a dictionary (dicQuestions)
    dicQuestions.Add CStr(oQst.QuestID), oQst

Based on the value of PAQuest  - if true I also add the object into another dictionary (dicPAQuestions)
    If oQst.PAQuest Then
          dicPAQuestions.Add CStr(oQst.QuestID), oQst
    End If

After loading all the questions, I stop (breakpoint) and run the following
    Debug.Print "Main: " & dicQuestions.Item("3217").Question
    Debug.Print "Main: " & dicQuestions.Item("3217").QuestAns

    Debug.Print "PA: " & dicPAQuestions.Item("3217").Question
    Debug.Print "PA: " & dicPAQuestions.Item("3217").QuestAns

    dicQuestions.Item("3217").QuestAns = True

    Debug.Print "Main: " & dicQuestions.Item("3217").Question
    Debug.Print "Main: " & dicQuestions.Item("3217").QuestAns

    Debug.Print "PA: " & dicPAQuestions.Item("3217").Question
    Debug.Print "PA: " & dicPAQuestions.Item("3217").QuestAns

My results are:
Main: Question Number 1
Main: False
PA: Question Number 1
PA: False

' This is where I set the QuestAns in the dicQuestions dictionary to TRUE

Main: Question Number 1
Main: True
PA: Question Number 1
PA: True <<<===== This is the problem
Why is the value in the dicPAQuestions changing?
I need the two dictionaries to be separate - the questions from each get answered at different times, and I need the results (question answered or not) to be kept separate.
Avatar of Martin Liss
Martin Liss
Flag of United States of America image

Why don't you create a Watch statement that will stop when the value of dicPAQuestions.Item("3217").QuestAns changes?

If you you don't know how to do that then see my article on debugging.
Avatar of Richard

ASKER

Hi Martin,
I set a break point after all the questions are loaded and dictionaries filled. Then I step through the 9 steps.  the first 4 steps show that the QuestAnswered value is False for both dictionaries.

At step 5 I change the value of the QuestAnswered value in the dicQuestions dictionary to TRUE.
            dicQuestions.Item("3217").QuestAnswered = True

At steps 6 - 9 I check the value of the QuestAnswered value in both dictionaries.
The value in the dicQuestions dictionary is TRUE as expected,
The value in the dicPAQuestions dictionary is also TRUE - very much unexpected.

I'm stepping (F8) and the program goes nowhere else.

I tried entering a watch statement:
dicPAQuestions.Item("3217").QuestionAnswered
to break when the value changes

An error is thrown 457 - "This key is already associated with an element of this collection line 510"

490                   dicQuestions.Add CStr(oQst.QuestID), oQst
500                   If oQst.PAQuestion Then
510                       dicPAQuestions.Add CStr(oQst.QuestID), oQst
520                   End If
This is in the load method - first time through.
Apparently the  watch statement adds some logic which modifies the class.
If I remove the watch statement, the error doesn't happen, the dictionaries get filled with all the data then the program breaks at my breakpoint where I test the value of the QuestionAnswered value as above.

Richard
Apparently the  watch statement adds some logic which modifies the class.
I strongly doubt that that ever happens.

How are your two dictionaries created? I ask because the code is acting like VBA is treating them as the same dictionary.
Avatar of Richard

ASKER

Hi Martin,
In my main declaration I have:
Public dicQuestions As Dictionary
Public dicPAQuestions As Dictionary

Then in my main startup routine I have:
    Set dicQuestions = New Dictionary
    Set dicPAQuestions = New Dictionary

Then later in my startup routine I call the procedure to load up the dictionaries.
At the beginning of the load method, I clear both dictionaries: dicQuestions.RemoveAll and dicPAQuestions.RemoveAll.

I strongly doubt that that ever happens.

Can you explain why there is an error with the watch statement in place and there is no error when I remove (Delete) the watch statement?

Richard
The only reason I can think of is that the watch will slow down processing a tiny bit and maybe doing that results in a duplicate key whereas without the watch the processing is faster and VBA doesn't get the chance to throw the error.

And just for laughs try defining the dictionaries like this

Public dicQuestions As New Dictionary
Public dicPAQuestions As New Dictionary

and comment out the Sets in the main startup routine.
ASKER CERTIFIED SOLUTION
Avatar of aikimark
aikimark
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Richard

ASKER

Hi Martin and aikimark,
Sorry about the delay in responding - I have been having Internet connection problems, my ISP is making a change which affects my static IPs and his performance and service!
Martin,  I tried revising the way the dictionaries are defined - no change.  Is there any advantage to using that syntax vs. my original syntax?

aikimark,  I'v been wondering about that, so I'm in the process of setting up a new object for the PADictionary.  I'll let you know as soon as I'm done.

A general question along these lines -
At the start of my load method I instance a new clsQuestion object.  After using that object, should I set it to Nothing before re-instancing it at the top of the load loop, or should I instance the object before the loop and use the same instance inside the loop?
Thanks for both of your quick replies.  Hopefully my ISP will keep things going for me!
Richard
I don't think you have to dereference it (set it to nothing).  As long as you create/instantiate a new one, it should work the way you want.
Avatar of Richard

ASKER

Hi aikimark,
That did the trick.  I created another object for use during the loading of the of the questions.  It makes my load twice as long - I load from SQL each value twice:
                oQst.Question = fQuestion.Value
                and
                oPQst.Question=fQuestion.value
for each parameter - however only 12 parameters so not too bad.
I'm just starting to get my head around to this OOP stuff and have to think more about references than I did with straight procedural programming.
Anyway,  thanks for the quick help.
Richard