Click here to Skip to main content
15,881,248 members
Articles / Programming Languages / Visual Basic

What Happens When You Use ByVal or ByRef

Rate me:
Please Sign up or sign in to vote.
4.00/5 (14 votes)
20 Feb 2010CPOL2 min read 56.2K   17   8
Demonstrates, with simple code, what happens when you pass a parameter ByVal or ByRef

Introduction

This is a common question asked on nearly every forum I have seen, and while the concept may seem simple, a quick look beneath the surface exposes some interesting things to remember:

Rule 1: When passing an Object (Reference Type) ByVal, a reference to the Object (not the variable) is passed. 

Rule 2: A variable (Value Type) passed ByVal is not affected by the code inside the method, while a variable passed ByRef is.

Example 1: Value Types 

To demonstrate, build and run this simple Console Application:

VB.NET
Public Module1

  Public Sub DoSomething(ByVal x As Integer, ByRef y As Double)

    x += 5
    y += 5

    Console.WriteLine("Inside Method Call:")
    Console.WriteLine("num= {0}", x.ToString)
    Console.WriteLine("anum = {0}", y.ToString)

  End Sub

  Sub Main()
    Dim num As Integer = 5
    Dim anum As Double = 20.5

    Console.WriteLine("Before Method Call:")
    Console.WriteLine("num = {0}", num.ToString)
    Console.WriteLine("anum = {0}", anum.ToString)

    DoSomething(num, anum)

    Console.WriteLine("After Method Call:")
    Console.WriteLine("num = {0}", num.ToString)
    Console.WriteLine("anum = {0}", anum.ToString)

    Console.Read()

  End Sub
End Module

Result:

Before Method Call:
num = 5
anum = 20.5

Inside Method Call:
num = 10
anum = 25.5

After Method Call:
num = 5
anum = 25.5

j0434929.png Note that in the code, we set two variables and initialize them:

VB.NET
Dim num as Integer = 5,
Dim anum as Double = 20.5

After displaying the initialized values, we call the method DoSomething(), supplying our variables as parameters. num is passed ByVal and anum is passed ByRef.

Check the results on your screen to see what has happened.

Because num was passed ByVal, no changes were made to the variable - a copy of the variable was passed into the method.

And, as anum was passed ByRef, any changes made in the method body will still be in effect after the method has completed.

Example 2 - Reference Types

Now that you have seen what happens when you pass value types ByVal and ByRef, let's see what happens when we pass Reference Types (objects).

 

Passing a value type to a method by value is equivilant to instantiating a new variable and assigning to it the first variable. This also applies to Reference Types.

Create a new console project:  

VB.NET
Module Module1

  Private Class Person

    Private _name As String

    Public Property Name() As String
      Get
        Return _name
      End Get
      Set(ByVal value As String)
        _name = value
      End Set
    End Property

    Public Sub New(ByVal name As String)
      _name = name
    End Sub

  End Class

  Private Sub ByValRefType(ByVal p As Person)
    p.Name = "Francis"
    Console.WriteLine("Inside method p = {0}", p.Name)
    p = Nothing
    ' Uncomment the line below to see what happens
    ' Console.WriteLine("Inside method after p deallocated p = {0}", p.Name)
  End Sub

  Sub Main()

    Dim p As Person = New Person("Jason")
    Console.WriteLine("Before Method Call p = {0}", p.Name)

    ByValRefType(p)

    Console.WriteLine("After Method Call p = {0}", p.Name)

    Console.ReadLine()

  End Sub

End Module 
Running this sample gives the following result:
Before Method Call p = Jason
Inside method p = Francis
After Method Call p = Francis

The referenced memory was changed (to Francis) but the p = Nothing statement had no effect on our originally declared variable p.

This is in contrast to when a Reference Type is passed ByRef...

VB.NET
Module Module1

    Class Person
        Private _name As String

        Public Property Name() As String
            Get
                Return _name
            End Get
            Set(ByVal value As String)
                _name = value
            End Set
        End Property

        Public Sub New(ByVal name As String)
            Me.Name = name
        End Sub

    End Class

    Public Sub DoSomething(ByVal person1 As Person, _
                           ByRef person2 As Person)

        person1.Name = "Changed Name"

        person2.Name = "Also Changed"

        Console.WriteLine("Inside Method:")
        Console.WriteLine("Person1 Name: {0}", person1.Name)
        Console.WriteLine("Person2 Name: {0}", person2.Name)

        person2 = New Person("Abel Tasman")
        Console.WriteLine("Person2 Name: {0}", person2.Name)
        Console.WriteLine()

        Person1 = Nothing    ' passed ByVal
        ' Dereference the memory holding Person2 (and p2) 
        Person2 = Nothing    ' passed ByRef

    End Sub

    Sub Main()
        Dim p1 As New Person("Captain Cook")
        Dim p2 As New Person("Vasco da Gama")

        Console.WriteLine("Before Method Call:")
        Console.WriteLine("Person1 Name: {0}", p1.Name)
        Console.WriteLine("Person2 Name: {0}", p2.Name)
        Console.WriteLine()

        DoSomething(p1, p2)

        Console.WriteLine("After Method Call:")
        Console.WriteLine("Person1 Name: {0}", p1.Name)
        Console.WriteLine("Person2 Name: {0}", p2.Name)	' NullReferenceException

        Console.Read()

    End Sub
End Module

Result:

Before Method Call:
Person1 Name: Captain Cook
Person2 Name: Vasco da Gama

Inside Method:
Person1 Name: Changed Name
Person2 Name: Also Changed
Person2 Name: Abel Tasman

After Method Call:
Person1 Name: Changed Name
' NullReferenceException here

j0434929.pngWe passed two Person parameters to the method DoSomething():

VB.NET
Dim p1 As New Person("Captain Cook")
Dim p2 as New Person("Vasco da Gama")

In the call to the method, the first argument p1 is passed ByVal, while the second argument p2 is passed ByRef as in the first example.

As the results show, When the parameter p2 is passed ByRef to the method (as Person2)and the memory is deallocated in the method body, the reference to Person for p2 is also deallocated. Hence the NullReferenceException when we tried to access the deallocated memory:

Console.WriteLine("Person2 Name: {0}", p2.Name)

Note also that the person2 = New Person("Abel Tasman") assignment in the method also points to the same memory location.

The result of the person1 = Nothing statement in the method is predictable and doesn't affect our p1 variable.

An Additional Thought

The beauty of passing a value type ByRef is that you can in-effect make a Sub into a "Function without a declared Return Type", and return more than one value from a Function!

History 

  • 29th November, 2009: Initial post
  • 30th November, 2009: Article updated  
  • 21st February, 2010: Article updated  

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Australia Australia
Born in New Zealand and transported to Australia for crimes against good taste in the eighties.

Employed by large Manufacturing Co to Coordinate Production Processes, Integrate new technologies, Implement new, in-house MRP/ERP.

Out of my depth, challenged and love it.

Comments and Discussions

 
GeneralMy vote of 1 Pin
Jecka16-Dec-09 0:03
Jecka16-Dec-09 0:03 
QuestionWhy is not this article erased from the Resource so far??? Pin
Jecka16-Dec-09 0:00
Jecka16-Dec-09 0:00 
GeneralPlease the correct the article or just scrp it if possible.,. It will misleads the begginers.,. Pin
Srinath Gopinath9-Dec-09 20:24
Srinath Gopinath9-Dec-09 20:24 
The explanation you have given is not fully correct [inaccurate]. Please edit it.,.

Check out the links given below:

http://msdn.microsoft.com/en-us/library/ddck1z30%28VS.71%29.aspx[^]

ByVal[^]

ByRef[^]
GeneralPassing a reference ByRef is not the same as ByVal. Pin
supercat92-Dec-09 7:23
supercat92-Dec-09 7:23 
GeneralThe only thing that should be ignored Pin
TimMahy20031-Dec-09 11:34
TimMahy20031-Dec-09 11:34 
GeneralInaccurate. Pin
dequadin29-Nov-09 7:33
dequadin29-Nov-09 7:33 
GeneralRe: Inaccurate. Pin
Andy_L_J29-Nov-09 18:11
Andy_L_J29-Nov-09 18:11 
GeneralRe: Inaccurate. Pin
dequadin30-Nov-09 2:06
dequadin30-Nov-09 2:06 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.