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.

Change History

Date

History

Reason

September 2009

Added topic.

Information enhancement.

See Also

VBScript Procedures
Function Statement (VBScript)
Sub Statement