Passing an argument ByRef
means that if someone assigns a new value to the variable, that new value will be passed back to the calling function. Passing it ByVal
passes a copy of that value to the function, so changes are not propagated back to the caller.
Note that when I refer to the value, it's what's actually stored in that variable. With reference types, that means that it's the reference. Passing a reference type by value does not copy the entire instance, it just copies the reference. This means that any changes made to the object itself will still be visible to the calling function.
For example, consider we have this class:
Public Class Foo
Private m_Value as string
Public Property Value as String
Get
return m_Value
End Get
Set(Value as String)
m_Value = Value
End Set
End Property
End Class
And in our program we have two functions:
Public Sub DoWork(ByVal obj as Foo)
obj = Nothing
End Sub
Public Sub DoWorkRef(ByRef obj as Foo)
obj = Nothing
End Sub
And we call them like this:
Dim obj1 as new Foo()
Dim obj2 as new Foo()
obj1.Value = "bar"
obj2.Value = "baz"
DoWork(obj1)
DoWorkRef(obj2)
At the end of this function, obj1
will still have a value, but obj2
will be Nothing
. This is because obj1
is being passed by value, so the code in DoWork
is operating on a copy of that variable (again, it's the same instance, it's just the variable that's different), whereas obj2
is being passed by reference, so it's pointing at the same variable as the main code.
To point out the "same instance", let's say we changed the functions to be like this:
Public Sub DoWork(ByVal obj as Foo)
obj.Value = "beep"
End Sub
Public Sub DoWorkRef(ByRef obj as Foo)
obj.Value = "bop"
End Sub
If we were to run the same code over again, we'd end up with obj1.Value
being equal to "beep", and obj2.Value
being equal to "bop". This is because even though we're passing obj1
by value, the value is a reference. You now just have two variables pointing at the same instance, so anything done do that instance will be reflected in both variables.
The important thing to remember is that the only effective difference between ByRef
and ByVal
comes when you assign a new value to the variable itself. All other behavior is effectively the same.
Post-Question-Edit Edit
You aren't passing a variable as the ByRef
parameter: you're passing a property. While C# will not allow this (because of this very issue), VB.NET will allow it. If you pass a property as a ByRef
parameter, it's essentially like doing this:
Dim _temp as String = b.Name
Foo(_temp)
b.Name = _temp
In other words, when passing a property as a ByRef
parameter, the setter for that property is always called using the value present in the variable after executing the function, even if the value didn't change.
It's a good rule of thumb not to pass properties as ByRef
parameters.