ByRef and ByVal Parameters
When you call a subroutine or function, each argument can be passed by reference or by value. When an argument is passed by reference, the called procedure can change the value of the variable. The change persists after the procedure is called. When an argument is passed by value, any changes that the called procedure makes to the value of the variable do not persist after the procedure is called.
In a Sub or Function declaration, each parameter can be specified as ByRef or ByVal. If neither is specified, the default is ByRef.
If ByVal is specified, the corresponding argument is always passed by value when the subroutine is called.
If ByRef (or neither) is specified, the argument can be passed by reference or by value when the subroutine is called. The argument is passed by value if it is enclosed in parentheses, and if the parentheses do not apply to the parameter list. The argument is also passed by value if the variable sent as an argument is in a class. Otherwise, it is passed by reference.
The following table summarizes this.
Keyword specified |
Argument is passed by |
---|---|
ByVal |
Value. |
ByRef (default) |
Reference or value, depending on other factors. |
Specifying ByRef and ByVal
In the following example, the ByRef keyword is specified for the MyParam variable. When the subroutine is called, a reference is passed to the variable MyArg. When the subroutine changes the value of MyParam, this also changes the value of MyArg. The local variable MyParam becomes an alias for MyArg.
Sub TestSub(ByRef MyParam)
MyParam = 5
End Sub
Dim MyArg
MyArg = 123
TestSub MyArg
' MyArg in changed in TestSub to 5.
In the following example, the ByVal keyword is used. Therefore, the argument is passed by value. The subroutine changes the value of MyParam. However, the value of MyArg remains unchanged.
Sub TestSub(ByVal MyParam)
MyParam = 5
End Sub
Dim MyArg
MyArg = 123
TestSub MyArg
' MyArg is still 123.
ByRef Is the Default
The default is ByRef if ByRef or ByVal is not specified. In this example, ByRef applies to the MyParam variable because neither ByRef nor ByVal is specified.
Sub TestSub(MyParam)
MyParam = 5
End Sub
Dim MyArg
MyArg = 123
TestSub MyArg
' MyArg is changed in TestSub to 5.
ByRef Parameters Passed by Value
If the parameter is specified as ByRef, the argument can still be passed by value. This occurs if one of the following is true:
The argument is in parentheses, and the parentheses do not apply to the argument list.
The variable sent as an argument is in a class.
The argument being passed is not a variable, for example, 12.
Argument in Parentheses
If the parameter is specified as ByRef, the argument can be passed by value if it is enclosed in parentheses. This is shown in the following example.
Sub TestSub(ByRef MyParam)
MyParam = 5
End Sub
Dim MyArg
MyArg = 123
TestSub (MyArg)
' MyArg is still 123.
A ByRef parameter is passed by value if the argument is enclosed in parentheses and the parentheses do not apply to the argument list.
The parentheses apply to the argument list if one of the following is true:
The statement is a function call that has an assignment to the returned value.
The statement uses the Call keyword. (The Call keyword can optionally be used for a subroutine call, or for a function call without an assignment.)
In the following example, the second call to TestFunction has an assignment to the returned value. For that call, the parentheses enclosing the argument list do not cause the ByRef parameter to be passed by value.
Function TestFunction(ByRef MyParam)
TestFunction = MyParam * 2
MyParam = 5
End Function
Dim MyArg, Result
MyArg = 123
TestFunction (MyArg)
' MyArg is still 123.
Result = TestFunction (MyArg)
' MyArg is changed in TestSub to 5.
In the following example, a Call keyword is used. The parentheses that enclose the argument list do not cause the ByRef parameter to be passed by value.
Sub TestSub(ByRef MyParam)
MyParam = 5
End Sub
Dim MyArg
MyArg = 123
Call TestSub ((MyArg))
' MyArg is still 123.
Call TestSub (MyArg)
' MyArg is changed in TestSub to 5.
In the following example, the function has two ByRef parameters. In the function call, one argument is passed by value and the other argument is passed by reference.
Function TestFunction(MyParam1, MyParam2)
' Both parameters are ByRef, because neither ByRef nor ByVal
' is specified for either parameter.
TestFunction = MyParam1 * MyParam2
MyParam1 = 5
MyParam2 = 6
End Function
Dim MyArg1, MyArg2, Result
MyArg1 = 123
MyArg2 = 124
Result = TestFunction ((MyArg1), MyArg2)
' MyArg1 is still 123.
' MyArg2 is changed in TestFunction to 6.
Argument in a Class
If the parameter is specified as ByRef, the argument is passed by value if the variable sent as an argument is in a class.
In the following example, the MyParam parameter is specified as ByRef. The method is called by using the cust.MyValue argument. Because cust.MyValue is inside a class, the argument is passed by value.
Class Customer
Public MyValue
End Class
Sub TestMethod (ByRef MyParam)
MyParam = 5
End Sub
Dim cust
Set cust = New Customer
cust.MyValue = 123
TestMethod cust.MyValue
' cust.MyValue is still 123.
See Also
Concepts
Reference
Change History
Date |
History |
Reason |
---|---|---|
September 2009 |
Added topic. |
Information enhancement. |