ByVal & ByRef in VB6 — When to use which?

One of the things new (or even experienced) VB6 programmers need to know about are the relevance/importance of ByVal and ByRef when passing parameters to a function or subroutine, as not knowing this could cause hard-to-detect bugs and unexpected results — and not being able to create more advanced codes.

ByVal

ByVal means pass “by value”, or pass a copy of the variable to the subroutine (or function) that will consume it. This means the argument passed to it is a copy of the modular variable. Any change performed on this argument will only take effect inside the subroutine (or function) and won’t translate outside.

ByRef

ByRef means to pass “by reference”, or to pass the memory address / reference / pointer of the variable to the subroutine (or function). We’re no longer passing a copy, but the actual variable, so if you modify this argument, the change would reflect outside the subroutine (or function).

Let’s see an example of using ByVal:

Sub some_process(ByVal some_number As Integer)
    some_number = 99
End Sub

Now, almost the same but using ByRef:

Sub another_process(ByRef another_number As Integer)
    another_number= 46
End Sub

In both subroutines, we tried to modify/change the arguments passed to it.

So let’s call them both and see what happens.

Here’s the code we’ll use to test them both:

Private Sub Form_Load()
    Dim flag                            As Integer
    
    flag = 12
    
    Debug.Print "Before Some Process:", flag
    some_process flag
    Debug.Print "After Some Process:", flag
    
    Debug.Print "Before Another Process:", flag
    another_process flag
    Debug.Print "After Another Process:", flag
End Sub

So what do you think the results would be for both calls?

If you run the codes, this is what you’ll see on the Immediate Window:

Before Some Process:         12 
After Some Process:          12 

Before Another Process:      12 
After Another Process:       46 

As you can see, the value of “flag” was retained (or stayed the same) after the call to “some_process” because it was passed ByVal but changed after the call to “another_process” completed since it was passed ByRef, and so changing it inside the subroutine would reflect that change on the modular variable.

Warning

In VB6, the default is “ByRef” so if you write subroutines (or functions) without specifying either ByVal or ByRef, then it’s effectively a “ByRef” argument. In our example above, this would be the same (and have the same effect):

Sub another_process(another_number As Integer)
    another_number = 46
End Sub

Note that there is no explicit indicator that it’s ByRef, but that’s the default. So be aware of this, and make it a habit to explicitly indicate how you’re passing these parameters.

Once you know these concepts, you would be able to make better designs of your subroutines (or functions), plus you’d be avoiding hard-to-find bugs.

There’s no right or wrong when using ByVal or ByRef as long as you understand why you’re using one or the other. They’re both tools to help you achieve some behavior, so design your codes accordingly.

I’ll expand on this a bit more and using a more relatable and useful examples on my next blog so stay tuned!

Leave a Comment