Variants are extremely useful, as I will discuss in the next section, but they do not work well with passing parameters by reference and can give rise to some hard-to-spot bugs. Of course, I am therefore willing to avoid passing by reference rather than forgo Variants.
The problem is illustrated in the example on the following page.
Private Sub f(ByVal x As Variant)
x = 6.4
Debug.Print x ' Shows 6.4
End Sub
Private Sub g(x As Variant)
x = 6.4
Debug.Print x ' Shows 6
End Sub
Private Sub Form_Load()
Dim i As Integer
i = 3
f i
g i
End Sub
The problem, as you can see, is that in the subroutine g, you might reasonably expect that after assigning 6.4 to g, which is declared in the parameter list as a Variant, Debug.Print would show 6.4. Instead it shows only 6.
Note that the only difference between functions f() and g() is that the parameter is passed ByVal in f() and ByRef in g().
When the function f is called, the actual parameter i is of type integer. Thus, in f the formal parameter x is created as a Variant of subtype integer and is initialized with the value 3. In other words, the subtype of the Variant within the function is defined by the type of the variable with which the function was actually called. When it is then set to the value 6.4, because x is a Variant it can accept this value and converts to a Variant of subtype double with the value 6.4. That much is straightforward.
When function g is called, Visual Basic has a bit of a problem. It is passing an integer by reference, so it cannot allow noninteger values to be placed in it. So instead of the integer being converted to a Variant, it remains an integer. Thus, even in the function g itself, where x is declared as a Variant, x is really an integer, and the assignment x = 6.4 will result in an implicit CInt call and x ends up with the value 6. Not so straightforward.
Functions such as f() are powerful because they can perform the same task no matter what the data type of the actual parameters is. They could even perform different tasks depending on the types of the actual parameter, although this can be confusing.
Functions such as g() lead to bugs. Avoid them by avoiding passing by reference.