Generalmente se suele usar ByVal en la programación de una función, por ejemplo
Private Sub (ByVal as ,...)
End Sub
pero tambien podemos escribir la función de la siguiente manera:
Private Sub (ByRef as ,...)
End Sub
¿Y cual es la diferencia?
Hay una gran diferencia al momento de usar ByVal y ByRef que se tiene que tener en cuenta a la hora de programar una función, y es que
El paso de argumento tipo ByVal crea una copia de la variable original, por lo que cualquier modificación hecha a dicha variable no afectará a la variable original.
El paso de argumento tipo ByRef hace una referencia de la variable original, por lo que cualquier modificación hecha a dicha variable si afectará a la variable original.
Para entender mejor en el siguiente ejemplo una variable inicializada en 10, cuyo valor se pasa a una función que lo incrementa en 1, debiendo obtener como resultado final 11.
Usando ByVal:
Dim suma As Integer = 10
fIncrementar(suma)
Private Sub fIncrementar(ByVal Value As Integer)
Value = Value + 1
End Sub
Si ejecutamos este ejemplo podremos comprobar que el item con valor 10 no aumenta a 11 porque en la función fIncrementar al usar ByVal creamos una copia de la variabel cuyo valor modificado no solo se aplicara a la variable orginal, el resutado final es que el número sigue siendo 10.
Usando ByRef:
Dim suma As Integer = 10
fIncrementar(suma)
Private Sub fIncrementar(ByRef Value As Integer)
Value = Value + 1
End Sub
Al usar ByRef prodremos comprobar que el valor de la variable suma que en un principio estuvo en 10 ahora aumento a 11, debido a que ByRef hace que la variable original se referencie en el argumento de la función fIncrementar, y cualquier cambio hecho al argumento Value se aplicará inmediatamente a la variable suma.
Otro caso en que es necesario conocer la diferencia entre Byval y ByRef es cuando queremos modificar una colección que esta siendo usado en un foreach, como se sabe no se puede agregar y tampoco eliminar items de una lista que esta siendo usado en un foreach, si se intenta hacer esto el compilador de visual estudio mostrará el siguiente error "Colección modificada; puede que no se ejecute la operación de enumeración.".
para poder realizar cambios a una colección mientras se usa en un foreach hay un truco usando ByRef .
En el siguiente ejemplo elimino un item de la colección cuando esta siendo usado en un foreach, para ello uso ByRef para hacer referencia a la lista que contiene los items, asi cualquier item que elimine en la función se actualizara en la lista original.
Dim lista As New List(Of Integer)
lista.Add(1)
lista.Add(2)
lista.Add(3)
For Each Item As Integer In lista.ToArray
If Item = 3 Then
fRemove(lista, Item)
End If
Next
Private Sub fRemove(ByRef lList As List(Of Integer), ByVal Item As Integer)
lList.Remove(Item)
End Sub
Con este truco podemos eliminar o agregar un item de la lista genérica mientras esta siendo usado en un foreach.