8.14. Passing Arrays: ByVal vs. ByRefA variable that "stores" an object, such as an array, does not actually store the object itself. Instead, the variable stores a reference to the object (i.e., the address of the location in the computer's memory where the object is stored). Recall that in Chapters 46, we discussed two types of variablesvalue types and reference types. The distinction between value-type variables and reference-type variables raises some subtle issues that you must understand to create secure, stable programs. Effects of ByVal on Value-Type Parameters and Reference-Type ParametersWhen used to declare a value-type parameter, keyword ByVal causes the value of the argument to be copied to a local variable in the method. Changes to the local variable are reflected in the local copy of the variable, but not in the original variable in the calling program. If the argument passed using keyword ByVal is of a reference type, the value copied is a reference to the original object in the computer's memory. Thus, reference types (like arrays and other objects) passed via keyword ByVal are actually passed by reference, meaning that changes made to the objects in called methods are actually made to the original objects in the callers. Performance Tip 8.1
Passing Reference Type Parameters Using ByRefVisual Basic also allows methods to pass references with keyword ByRef. This is a subtle capability, which, if misused, can lead to problems. For instance, when a reference-type object like an array is passed with ByRef, the called method actually gains control over the original reference in the caller, allowing the called method to replace the reference with one to a different object or even with Nothing. Such behavior can lead to unpredictable effects, which can be disastrous in business-critical and mission-critical applications. The program in Fig. 8.22 demonstrates the subtle difference between passing a reference ByVal and passing a reference ByRef. Figure 8.22. Passing an array reference with ByVal and ByRef.
Lines 67 declare two Integer array variables, firstArray and firstArrayCopy (we make the copy so that we can determine whether the reference firstArray gets overwritten by method FirstDouble). Line 10 allocates an array containing Integer values 1, 2 and 3 and stores the array reference in variable firstArray. The assignment statement at line 11 copies the reference firstArray to the reference variable firstArrayCopy, causing these variables to reference the same array object. The For...Next statement in lines 1719 prints the contents of firstArray before it is passed to method FirstDouble at line 21 so we can verify that this array is passed by reference (i.e., the called method indeed changes the array's contents in Main). The For...Next statement in method FirstDouble (lines 7678) multiplies the values of all the elements in the array by 2. Line 81 allocates a new array containing the values 11, 12 and 13; the reference for this array then is assigned to parameter array (in an attempt to overwrite reference firstArray in Mainthis, of course, does not happen, because the reference firstArray was passed ByVal). After method FirstDouble executes, the For...Next statement in lines 2628 prints the contents of firstArray, demonstrating that the values of the elements have been changed by the method FirstDouble (and confirming that in Visual Basic arrays are always passed by reference). The If statement in lines 3135 uses the Is operator to compare references firstArray (which we just attempted to overwrite) and firstArrayCopy. Visual Basic provides operator Is for comparing references to determine whether they are referencing the same object. The expression at line 31 is true if the operands to the binary operator Is reference the same object. In this case, the object represented is the array allocated in line 10not the array allocated in method FirstDouble (line 81). Visual Basic also provides operator IsNot for comparing two references. If two references refer to the same objects, operator IsNot returns False; otherwise it returns true. Line 81 modifies only the parameter array, not the variable firstArray because firstArray was passed with keyword ByVal. We will see in a moment the effect of passing an array with keyword ByRef. Lines 3869 in method Main perform similar tests, using array variables secondArray and secondArrayCopy and method SecondDouble (lines 8694). Method SecondDouble performs the same operations as FirstDouble, but receives its array argument with ByRef. In this case, the reference stored in secondArray after the method call is a reference to the array allocated at line 93 of SecondDouble, demonstrating that a reference passed with ByRef can be modified by the called method so that the reference actually points to a different object, in this case the array that is allocated in method SecondDouble. The If statement in lines 6569 determines that secondArray and secondArrayCopy no longer represent the same array. Software Engineering Observation 8.2
|