Scott Scovell on Visual FoxPro

Thursday, December 01, 2005

AMEMBERS Gotcha

Again, here I hope to save a few fellow tax payers some time and possibly hardware. I have just spent two to three hours on this one and my head is still spinning. I'm joking about the hardware, I have a strict "three strikes and out" policy towards cruelty to IO devices.
 
I was unit testing some code I was writing for VFP Solution Explorer. The code was doing some type discovery of sorts on some user defined class instances based on the Empty class. In particular, I was using AMEMBERS() to place the properties of the passed object into an array.
 
I had similar code in a number of places and it was working in all but one. After a lengthy process of elimination, it turned out the only difference was the code that was failing was inside a FOR EACH...NEXT loop.
 
The following sample code demonstrates this
 

Local oCollection As Collection, oUser As Object, lnIndex As Integer

 

* Create an instance of a collection class so we can iterate

*     through the collection using For Each..Next and For..Next

oCollection = NewObject("Collection")

 

* Add a couple user defined objects to the collection

For lnIndex = 1 to 3

 

      * Create an user defined object with a couple of properties

      oUser = NewObject("Empty")

      AddProperty(oUser, "Property1", "Value1")

      AddProperty(oUser, "Property2", "Value2")

 

      * Add to collection

      oCollection.Add(oUser) 

Next

 

* Output the number of properties returned by AMembers() when

*     passed our user defined object in different ways

Clear

? "* First item of collection" + Chr(9), "Properties found: ", AMembers(laAtttributes, oCollection(1), 0)

 

* Using a For Each...Next loop

For Each oUser In oCollection

      ? "* For Each loop" + Chr(9) + Chr(9), "Properties found: ", AMembers(laAtttributes, oUser, 0)

      Exit

Next

 

* Using a For...Next loop

For lnIndex = 1 To oCollection.Count

      oUser = oCollection.Item(lnIndex)

      ? "* For Next loop" + Chr(9) + Chr(9), "Properties found: ", AMembers(laAtttributes, oUser, 0)

      Exit

Next

 
Notice, when inside a FOR EACH..NEXT loop, AMEMBERS() fails to retrieve any property information from the user defined object.
 
I favour using FOR EACH...NEXT loops over FOR...NEXT loops as I like to work with collections over arrays. But even when using arrays, Fox allows me to keep consistent and use FOR EACH...NEXT loops when iterating through arrays...perhaps not?
 
Powered By Qumana

6 Comments:

  • Try your code with the additional FOXOBJECT keyword attached to the FOR EACH. The reason behind this is, that collections are somewhat strangely integrated in VFP, they are handled by the _VFP engine, i.e. via the COM-Object layer. Therefor you normally don't have a direct pointer to the real object.

    By Blogger wOOdy, at December 02, 2005 9:26 pm  

  • Scott,

    I'm trying to subscribe to your blog. Where do I find your atom.xml file?

    ++Alan

    By Blogger ++Alan, at December 10, 2005 2:01 am  

  • Hi ++Alan,

    This is the url to the feed:

    http://scottscovellonvfp.blogspot.com/atom.xml

    I use Sage (FireFox extension) as my reader and this is the url used.

    Others have mentioned that feed validators report some errors with my feed (see here) and perhaps this is causing your reader problems.

    I'll look into these issue when I next get some time.

    Thanks again

    Scott

    By Blogger Scott Scovell, at December 10, 2005 9:23 am  

  • Yes, as Woody said, I've noticed that using the FOR EACH doesn't access the object directly but goes through a COM interface to the object.

    I haven't used the FOXOBJECT clause, I tend to just stay away from FOR EACH now, I've been bitten too many times :(

    By Blogger Tom, at December 13, 2005 10:47 pm  

  • Scott,

    Sage can't parse the atom.xml, and Firefox gives a "prefix not bound to a namespace" error when trying to view it.

    IE in all its mellow "wisdom" displays the file just fine.

    ++Alan

    By Blogger ++Alan, at December 16, 2005 3:06 am  

  • Scott,

    yes, this is a lovely way to go knuts.
    Another For...each gotcha is dealing with dates that, due to the COM - issue, become datetimes.

    So
    for each loItem in this
    ? loItem.dDate
    endfor

    returns dateTime

    this issue gets me about every once in a year as all my methods do type-checking and thus fail on working properly

    Procedure DoDate(tdDate as date) as boolean
    tdDate = iif(vartype(tdDate)="D", tdDate, {//})

    Frank

    By Blogger DDTech, at March 16, 2008 8:37 pm  

Post a Comment

<< Home