As long as I can remember, there has always been confusion about ByVal
and ByRef
/ref
parameters. Here's the best way I can explain it:
You only need to pass an object by reference if and only if you plan on replacing that reference with a different reference. If you want to change the contents of the object being passed, you only need to pass it by value. Example:
Public Class Person
Public Property FirstName As String
Public Property LastName As String
End Class
Public Shared Sub ModifyPerson(ByVal someone As Person)
' Passed by value ^^^^^
someone.LastName = "Doe"
End Sub
Public Shared Sub Main(ByVal args() As String)
Dim me As New Person
me.FirstName = "Adam"
me.LastName = "Maras"
ModifyPerson(me)
Console.WriteLine(me.LastName) ' Writes "Doe"
End Sub
Yes, the instance of Person
called me
is passed into ModifyPerson
by value; that just means the reference to the instance is passed by value. A function can still modify the members of that reference. Now, try this:
Public Shared Sub Main(ByVal args() As String)
Dim me As New Person
me.FirstName = "Adam"
me.LastName = "Maras"
AssignByValue(me)
Console.WriteLine(me.LastName) ' Writes "Maras"
AssignByReference(me)
Console.WriteLine(me.LastName) ' Writes "Doe"
End Sub
Public Shared Sub AssignByValue(ByVal someone As Person)
Dim new As New Person
new.FirstName = "John"
new.LastName = "Doe"
someone = new
End Sub
Public Shared Sub AssignByReference(ByRef someone As Person)
Dim new As New Person
new.FirstName = "John"
new.LastName = "Doe"
someone = new
End Sub
These functions differ because they try to modify the actual reference being passed in. AssignByValue
has no effect on the Person
named me
because the parameter is passed by value. However, AssignByReference
can change the value of that parameter in the method that called it, hence why the second call to Console.WriteLine(me.LastName)
reflects the updated reference.