The parameters of called procedures or functions can be passed by value or by reference. This section describes the difference between these two techniques.
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.
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.
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.
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 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.