Parameter Passing

The parameters of called procedures or functions can be passed by value or by reference. This section describes the difference between these two techniques.

By Value Parameters

When a parameter is passed by value it acts like a local variable in the called procedure or function. Changes made to the value parameter inside method the do not affect the value of the passed variable outside the method. i.e. the called method is only passed the value of the passed variable or expression, not the variable itself. This is the default behavior of procedure or method parameters in DataFlex.

By Reference Parameters

When a parameter is passed by reference, the called procedure or function has direct read/write access to the passed variable. Changes made to the reference parameter inside the method are reflected in the passed variable outside the method.

This technique is often applied when there’s a need for multiple return values, or for in-out parameters which pass one value to the called method and are allowed to be modified and contain a different value when the execution returns to the caller. The latter is commonly used in COM event methods, as a means of allowing the client code to cancel or modify a certain action or default behavior.

Declaring By Reference Parameters

To specify that a parameter is to be passed by reference you must precede the parameter with the ByRef symbol in the procedure/function declaration. For example:

Procedure AddOne Integer ByRef iValue

    Move (iValue + 1) to iValue

End_Procedure

 

Integer iCount

Move 0 to iCount

Send AddOne (&iCount)

The above procedure declares one by reference parameter (iValue). When the procedure is called the integer variable that it passed to the procedure will be incremented by 1.

Passing Arguments using the '&' (by reference) Operator

To pass an argument by reference rather than by value, you must prefix the passed parameter with the unary & operator. The prefix and parameter must be enclosed in an expression (that is, the & operator and variable name must be enclosed within parentheses). The passed parameter must also be a variable. e.g. (&MyVariable) will pass on MyVariable by reference rather than by value. This enables the called method to modify the contents of MyVariable directly, so that when the call returns, MyVariable may contain a different value.

The following is an example of passing an argument by reference:

Procedure GetData String ByRef sData

    Move "Here is some data" to sData

End_Procedure

 

String sMyString

Send GetData (&sMyString)

// The value of sMyString is now "Here is some data"

Array and Struct Parameters

Array and struct parameters automatically utilizes the copy-on-write concept. So passing an array/struct by value does not cause the entire array/struct to be copied into a new memory location, unless the procedure or function modifies any value in the array/struct. For example, the WriteNames procedure in the examples below is memory efficient because it is only reading values from the array.

Struct tNameStruct

    string FirstName

    string LastName

End_Struct

 

tNameStruct[] gStudents

 

Procedure ReadNames Global tNameStruct[] byRef Names

    String  sFirstName sLastName

    Integer iCount

    Move 0 to iCount

    Direct_Input "Names.txt"

    While (Not(seqeof))

        Readln sFirstName sLastName

        If (Not(seqeof)) Begin

            Move sFirstName to Names[iCount].FirstName

            Move sLastName  to Names[iCount].LastName

            Increment iCount

        End

    Loop

    

    Close_Input        

End_Procedure

 

Procedure WriteNames Global tNameStruct[] Names

    Integer iName icName

    Move (SizeOfArray(Names)) to icName

    For iName from 0 to (icName – 1)

        Showln Names[iName].FirstName " " Names[iName].LastName

    Loop

End_Procedure

 

Send ReadNames (&gStudents)

Send WriteNames gStudents

The procedure ReadNames is passed a reference to a tNameStruct array (i.e. a by reference parameter). The procedure fills the array with values read from a text file. ReadNames uses by reference parameter passing because it is modifying the contents of the array.

The procedure WriteNames lists each element in the tNameStruct array passed to it. WriteNames does not need to pass the array by reference because it is only reading values from the array, so the contents of the array is not copied even though it’s passed by value due to the built-in copy-on-write optimization for struct/array parameter types.