Arguments

mshahid

Active member
Joined
Aug 23, 2012
Messages
29
Programming Experience
Beginner
Kindly let me know that what is the diffeence between By value argument and by reference arguments.

Thanks
 
Rather than going into the details of the difference in implementation, I will tell when and why to use each. First of all, ByVal is the default mechanism and is what you should use unless you have a specific need to pass by reference. Here is how ByVal and ByRef work for value types, which basically means structures:
Private Sub CallingMethod()
    Dim val As SomeStructure

    val.SomeProperty = "Initial Value"
    CalleeMethod(val)

    'This will show "Initial Value", i.e. the change in the method has NOT affected the original variable.
    MessageBox.Show(val.SomeProperty)
End Sub

Private Sub CalleeMethod(ByVal arg As SomeStructure)
    'Change a property value of the argument.
    arg.SomeProperty = "Final Value"
End Sub
Private Sub CallingMethod()
    Dim val As SomeStructure

    val.SomeProperty = "Initial Value"
    CalleeMethod(val)

    'This will show "Initial Value", i.e. the change in the method has NOT affected the original variable.
    MessageBox.Show(val.SomeProperty)
End Sub

Private Sub CalleeMethod(ByVal arg As SomeStructure)
    'Assign a new value to the argument.
    arg = New SomeStructure()
    arg.SomeProperty = "Final Value"
End Sub
Private Sub CallingMethod()
    Dim val As SomeStructure

    val.SomeProperty = "Initial Value"
    CalleeMethod(val)

    'This will show "Final Value", i.e. the change in the method HAS affected the original variable.
    MessageBox.Show(val.SomeProperty)
End Sub

Private Sub CalleeMethod(ByRef arg As SomeStructure)
    'Change a property value of the argument.
    arg.SomeProperty = "Final Value"
End Sub
Private Sub CallingMethod()
    Dim val As SomeStructure

    val.SomeProperty = "Initial Value"
    CalleeMethod(val)

    'This will show "Final Value", i.e. the change in the method HAS affected the original variable.
    MessageBox.Show(val.SomeProperty)
End Sub

Private Sub CalleeMethod(ByRef arg As SomeStructure)
    'Assign a new value to the argument.
    arg = New SomeStructure()
    arg.SomeProperty = "Final Value"
End Sub
So, if you pass a value type argument by value then no change you make inside the method will affect the original and if you pass it by reference then any and all changes you make inside the method.

Here is how ByVal and ByRef work for value types, which basically means structures:
Private Sub CallingMethod()
    Dim val As New SomeClass

    val.SomeProperty = "Initial Value"
    CalleeMethod(val)

    'This will show "Final Value", i.e. the change in the method HAS affected the original variable.
    MessageBox.Show(val.SomeProperty)
End Sub

Private Sub CalleeMethod(ByVal arg As SomeClass)
    'Change a property value of the argument.
    arg.SomeProperty = "Final Value"
End Sub
Private Sub CallingMethod()
    Dim val As New SomeClass

    val.SomeProperty = "Initial Value"
    CalleeMethod(val)

    'This will show "Initial Value", i.e. the change in the method has NOT affected the original variable.
    MessageBox.Show(val.SomeProperty)
End Sub

Private Sub CalleeMethod(ByVal arg As SomeClass)
    'Assign a new value to the argument.
    arg = New SomeClass()
    arg.SomeProperty = "Final Value"
End Sub
Private Sub CallingMethod()
    Dim val As New SomeClass

    val.SomeProperty = "Initial Value"
    CalleeMethod(val)

    'This will show "Final Value", i.e. the change in the method HAS affected the original variable.
    MessageBox.Show(val.SomeProperty)
End Sub

Private Sub CalleeMethod(ByRef arg As SomeClass)
    'Change a property value of the argument.
    arg.SomeProperty = "Final Value"
End Sub
Private Sub CallingMethod()
    Dim val As New SomeClass

    val.SomeProperty = "Initial Value"
    CalleeMethod(val)

    'This will show "Final Value", i.e. the change in the method HAS affected the original variable.
    MessageBox.Show(val.SomeProperty)
End Sub

Private Sub CalleeMethod(ByRef arg As SomeClass)
    'Assign a new value to the argument.
    arg = New SomeClass()
    arg.SomeProperty = "Final Value"
End Sub
In the case of reference types, making a change to a property of the argument inside the method will affect the original regardless of whether you use ByVal or ByRef. If you assign a new value to the argument itself, that will only affect the original if you pass ByRef and not ByVal.
 
One reason to pass arguments by reference is for example passing a very large object, or many large objects successively. Passing ByVal in this case makes a copy of each object passed, so it might incur some slowdown. Passing ByRef just passes a pointer to the original object in memory, so it is faster.

Keep in mind that this only applies in the case of very large objects, for standard purposes there will be little to no difference in delay.
 
One reason to pass arguments by reference is for example passing a very large object, or many large objects successively. Passing ByVal in this case makes a copy of each object passed, so it might incur some slowdown. Passing ByRef just passes a pointer to the original object in memory, so it is faster.

Keep in mind that this only applies in the case of very large objects, for standard purposes there will be little to no difference in delay.

That is not valid in VB.NET. It was the case in VB6, where ByRef was used exactly as you say, i.e. to prevent large objects being copied. In VB.NET, the vast majority of types are classes and classes are reference types. If you pass a reference type by value then you make a copy alright, but you only make a copy of the reference to the object, not the object itself. No matter how big the object is, the reference to it will only be 32 or 64 bits in size.

Passing structures by value is a different kettle of fish. Structures are value types so passing a structure by value does make a copy of the object. There is a rule of thumb for .NET types though, that says that any type that occupies more than 16 bytes should be a class. That means that no value type should ever be so big that making a copy of it should be an issue.

With those two points in mind, when using VB.NET there is one and only one reason to use ByRef: because you want a change you make to an argument inside a method to affect the original value. As you can see from my examples, any changes you make to a reference type passed by value affect the original anyway, so that only leaves three change types that require you to use ByRef:

1. Assigning a new value to a reference type argument itself.
2. Modifying a value of a field/property of a value type argument.
3. Assigning a new value to a value type argument itself.

If you want any one of those three types of changes to affect the original value then you must use ByRef. Under any other circumstances you should use ByVal. There are basically no exceptions. The only scenario that could be considered an exception would be a large value type, but they should pretty much never exist anyway. The one, very rare scenario that would be an acceptable exception would be where you have to define a large type as a structure because it is required by unmanaged code and you have a need to pass instances of that type to a method other than an unmanaged function. Like I said, that will happen very rarely.
 
Back
Top