none
VB Script, arrays and classes RRS feed

  • General discussion

  • Hi people

    I'm running into a problem involving array reference.

    In the following code, there is a simple class and one of its properties (namely "elements") is an array. Next, the class is instanciated and bound to the "var1" object variable. It should follow that "var1.elements" refers to the instance array.

    Next, I try to assign a string value to the first 'cell' of the instance array :

    var1.elements(0) = "hello"

    and an anonymous array (through the Array(...) construct) is assigned to the second cell :

    var1.elements(1) = Array("it's a beautiful day")

    I can print out the values of var1.elements(0) and var1.elements(1)(0) without problems, but it's a different story attempting to modify the value of 'embedded' array :

    var1.elements(1)(0) = "some other value"

    ... just doesn't work. It throws no errors, but the programmes behaves like var1.elements(1) returns a copy of the 'embedded' array and thus does not modify it. I mean that printing out var1.elements(1)(0) still displays "it's a beautiful day"

    How come?

    This behaviour doesn't occur using regular arrays instead of object variables :

    dim var1(10)

    var1(0) = Array("some value")

    var1(0)(0) = "some other value"      >>> the 'embedded' array assignment is correctly taken into account.

    class Test public elements() public sub Class_Initialize() redim elements(10) end sub end class REM ---------------------------------------------- dim var1 set var1 = new Test var1.elements(0) = "hello" var1.elements(1) = Array("it's a beautiful day") WScript.echo var1.elements(0), var1.elements(1)(0) REM >>> will display "hello it's a beautiful day"

    var1.elements(0) = "yes it is" var1.elements(1)(0) = "and how are you?" WScript.echo var1.elements(0), var1.elements(1)(0)

    REM >>> will display "yes it is it's a beautiful day"

    Thanks in advance for your input.
    Sunday, June 28, 2015 8:41 PM

All replies

  • Yes that is the behavior of arrays embedded in classes.  Use  Get/Set to adjust a class.  THe assigned array is only a reference and not a copy so it is not accessible.


    \_(ツ)_/

    Sunday, June 28, 2015 10:15 PM
  • Thanks for your reply but I'm afraid I don't understand.

    > THe assigned array is only a reference and not a copy so it is not accessible.

    Are you saying that 

    var1.elements(0) = Array(0,1)

    will assign a reference to the anonymous array to elements(0), and because of that it is not accessible for manipulations outside of the class?

    I have conducted the following tests about this class/array problem :

    class Test
    
        public elements()
        
        public sub Class_Initialize()
            redim elements(0)
        end sub
    
        sub addArrayFromClass
            elements(0) = Array("M", "N")
        end sub
    
    end class
    
    REM ----------------------------------------------
    
    dim var1, obj
    
    set var1 = new Test
    
    ' test with string value - OK
    var1.elements(0) = "test"
    var1.elements(0) = "other"
    WScript.echo var1.elements(0)                   ' >>> other
    
    
    ' test with object reference - OK
    set obj = WScript.CreateObject("Scripting.Dictionary")
    obj.item("greetings") = "hello"
    set var1.elements(0) = obj
    var1.elements(0).item("greetings") = "there"
    WScript.echo var1.elements(0).item("greetings") ' >>> there
    WScript.echo obj.item("greetings")              ' >>> there
    
    
    ' test with anonymous array - FAIL
    var1.elements(0) = Array(0, 1)
    var1.elements(0)(0) = 2
    WScript.echo var1.elements(0)(0)                ' >>> 0
    
    ' test with copy of other array variable - FAIL
    redim myArray(1)
    myArray(0) = "A"
    myArray(1) = "B"
    var1.elements(0) = myArray
    var1.elements(0)(0) = "Z"
    WScript.echo var1.elements(0)(0)                ' >>> A
    WScript.echo myArray(0)                         ' >>> A
    
    ' test with anonymous array assigned from inside class - FAIL
    var1.AddArrayFromClass
    WScript.echo var1.elements(0)(0)                ' >>> M
    var1.elements(0)(0) = "L"
    WScript.echo var1.elements(0)(0)                ' >>> M
    

    So it seems that it is possible to manipulate the contents of a class array with strings, numbers, objects, but not embedded arrays. This is very annoying and unintuitive. What's the logic behind that?

    Sunday, June 28, 2015 11:39 PM
  • That is correct.  You cannot do that.  You can supply setter/getter methods and use specific "in-object" methods to manipulate arrays embedded in objects.


    \_(ツ)_/

    Monday, June 29, 2015 2:30 AM
  • You can replace the reference but not the elements:

    class Test
        public elements(2)
    end Class
    
    set var1 = new Test
    var1.elements(0) = "hello"
    var1.elements(1) = Array("it's a beautiful day")
    
    WScript.echo var1.elements(0), var1.elements(1)(0)
    
    var1.elements(0) = "yes it is"
    var1.elements(1) = Array("and how are you?")
    
    WScript.echo var1.elements(0) ,var1.elements(1)(0)


    \_(ツ)_/


    • Edited by jrv Monday, June 29, 2015 2:33 AM
    Monday, June 29, 2015 2:32 AM
  • Consider the following:

    class Test
        public elements(2)
    end Class
    
    set var1 = new Test
    
    var1.elements(0) = "hello"
    var1.elements(1) = Array("it's a beautiful day")
    
    WScript.echo var1.elements(0), var1.elements(1)(0)
    
    var1.elements(0) = "yes it is"
    a2=Array("and how are you?")
    var1.elements(1) = a2
    
    WScript.echo var1.elements(0) ,var1.elements(1)(0)
    
    a2(0) = "XXXXXXXXXXXXXXXX"
    WScript.Echo "A2  ===  " & a2(0)
    var1.elements(1) = a2
    WScript.Echo  "ELEMENTS ====== " & var1.elements(1)(0)
    
    var1.elements(1)(0) = "YYYYYYYYYY"
    WScript.Echo "ELEMENTS 1 ===== " & var1.elements(1)(0)
    WScript.Echo "A2  =====" & a2(0)
    


    \_(ツ)_/

    Monday, June 29, 2015 2:42 AM
  • Thanks for these examples. Unfortunately a property get/let/set type of solution would be highly impractical in the case of multiple embedded arrays (i.e. a class array containing an array that contains another array). My project involves a class of extensible arrays to be used in another class, and I need that other class to access directly to the content of the xArray.

    Since I want something purely VBS (no ArrayList), the only workaround I can think of, is to reinvent the wheel and completely discard the use of anonymous arrays.

    class ArrayObject
    
        private my_elements()
        private my_count
        
        public sub Class_Initialize
            redim my_elements(49)
            my_count = 0
        end sub 
        
        public default property get item(index)
            if isObject( my_elements(index) ) then
                set item = my_elements(index)
            else
                item = my_elements(index)
            end if
        end property
        
        public property let item(index, value)
            if index < 0 or index >= my_count then err.raise 1, "ArrayObject", "subscript out of range"
            my_elements(index) = value
        end property
        
        public property set item(index, object)
            if index < 0 or index >= my_count then err.raise 1, "ArrayObject", "subscript out of range"
            set my_elements(index) = object
        end property
        
        public property get count
            count = my_count
        end property
        
        public sub add(any_type)
            if my_count >= ubound(my_elements) then redim preserve my_element(my_count + 49)
            if isObject(any_type) then
                set my_elements(my_count) = any_type
            else
                my_elements(my_count) = any_type
            end if
            my_count = my_count + 1
        end sub
        
    end Class
    
    dim var1
    
    set var1 = new ArrayObject
    
    var1.add "it's a boring hot"
    
    var1.add new ArrayObject
    
    var1(1).add "day,"
    var1(1).add "and VBScript arrays are outrageously quirky"
    
    WScript.echo var1(0), var1(1)(0), var1(1)(1)
    
    var1(1)(1) = "and next time I'll pick a trustworthy scripting language"
    
    WScript.echo var1(0), var1(1)(0), var1(1)(1)
    

    Next time I'll convince my client to install Python.

    Tuesday, June 30, 2015 10:39 PM
  • Life, at times, can be very disappointing.  I think you should consider a hobby that does not include computers.  I like fishing and horseshoes myself.

    \_(ツ)_/

    Tuesday, June 30, 2015 10:43 PM
  • Microsoft, oftentimes, can be very disappointing ...

    \_(ツ)_/

    So true. Thank goodness there is competition.
    Tuesday, June 30, 2015 11:02 PM
  • Microsoft, oftentimes, can be very disappointing ...


    \_(ツ)_/

    So true. Thank goodness there is competition.

    Sneaky - sneaky.

    Where?  In Zanobia?  Even Groucho refused to go to Zanobia.


    \_(ツ)_/

    Tuesday, June 30, 2015 11:19 PM