ASNA Knowledge Base
Technical references, how-tos, and trouble-shooting for ASNA products

AVR for .NET arrays: arrays as arguments

You can easily pass an AVR for .NET array, as an argument, to subroutines and functions. To do so, the DclSrParm that receives the array must be declared as a ranked array (remember, rank means number of dimensions). However the array that you pass may have been declared, as either a ranked or dimmed array, the distinction is that regardless of how the array is declared, when passed to a subroutine or function, the array will be seen as a ranked array.

In the example that follows, MyRoutine passes the ranked array MyArr to a routine Test1.

DclArray MyArr Type(*Integer4) Rank(1)

MyArr = *New *integer4[] { 24, 30, 36, 42 }

Test1(MyArr)

...

BegSr Test1
    DclSrParm InArr Type(*Integer4) Rank(1) 
    .         
    .         
    Test1 has the contents of MyRoutine's array available
    to it here--as the InArr array.
    .         
    .         
EndSr

or with a dimmed array:

DclArray MyArr Type(*Integer4) Dim(4)

MyArry[0] = 24
MyArry[1] = 30
MyArry[2] = 36
MyArry[3] = 42

Test1(MyArr)

...

BegSr Test1
    DclSrParm InArr Type(*Integer4) Rank(1) 
    .         
    .         
    Test1 has the contents of MyRoutine's array available
    to it here--as the InArr array.
    .         
    .         
EndSr

Note that Test1 won’t explicitly know how many elements are in the InArr array. If Test1 needs to traverse the InArr, it needs to use either the For/Each, the array’s GetUpperBound() method, or the array’s Length property. Don’t ever assume the array bounds in called routines–always use softcoded techniques for determining the upper bounds of the passed array.

It’s also important to note that you use DclSrParm to declare array arguments to functions and subroutines, but you must also include the Rank() keyword to indicate that parameter is an array.

Arrays are reference types

Because arrays are reference types they are implicitly passed by reference. Thus, any changes made in the called routine are reflected in the caller. This is illustrated in the code below. The zeroth element of MyArr is 24 below the call to Test1; after the call to Test1 its value is 189.

DclArray MyArr Type(*Integer4) Rank(1)

MyArr = *New *integer4[] { 24, 30, 36, 42 }

// MyArr[0] is now 24.

Test1(MyArr) 
// After the call, MyArr[0] is 189. 

BegSr Test1
    DclSrParm InArr Type(*Integer4) Rank(1) 
    .         
    .         
    InArr[0] = 189
    .         
EndSr

In .NET, by default, arguments are passed by value. So, the above behavior is probably not the behavior a beginning AVR for .NET programmer expects. (In AVR Classic, changes to arguments passed by value were not seen by the caller). However, when .NET reference types are passed by value, they have pass-by-reference semantics when values are changed. The notion of reference types being passed by value is a concept that will raise its pointy head time and time again in AVR for .NET. Get very familiar with it! Read more about value and reference types here.

Redimension arrays

You cannot explicitly redimension arrays in AVR for .NET. The ReDim operation is specific to VB. It is not a .NET operation and therefore also not available to AVR or C#. However, the fact that arrays are reference types can be exploited to implement your own array redimensioning. Pay close attention to the code that follows—it has a few subtleties.

BegSr MyRoutine     
    DclArray MyArr Type(*Integer4) Rank(1)

    MyArr = *New *integer4[] { 24, 30, 36, 42 }
    // MyArr has four elements.

    MyArr = ReDimMyArr(MyArr, 8) 
    // Now MyArr has eight elements. 
EndSr

BegFunc ReDimMyArr Type(*Integer4) Rank(1) 
    DclSrParm InArr  Type(*Integer4) Rank(1) 
    DclSrParm ElementCount Type(*Integer4)

    DclArray MyArr Type(*Integer4) Rank(1)

    MyArr = *New *Integer4[ElementCount]        
    Array.Copy(InArr, MyArr, InArr.Length)

    LeaveSr MyArr
EndFunc

Because MyArr was passed by value to ReDimMyArr() the returned reference to a new array (with the number of elements provided) is assigned to MyArr in MyRoutine. This effectively reassigns a new array to the MyArr in MyRoutine. This technique wouldn’t work if MyArr was passed to ReDimMyArr() by reference.

In Part 5, we’ll take a look at the convert record format data into an array.

Published: Jan 9, 2024
visual-rpg