Click here to Skip to main content
Licence CPOL
First Posted 29 Nov 2009
Views 10,187
Bookmarked 13 times

What Happens When You Use ByVal or ByRef

By Andy_L_J | 20 Feb 2010
Demonstrates, with simple code, what happens when you pass a parameter ByVal or ByRef
1 vote, 8.3%
1

2
6 votes, 50.0%
3

4
5 votes, 41.7%
5
3.96/5 - 12 votes
1 removed
μ 3.83, σa 2.28 [?]

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:

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:

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:  

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...

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():

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)

About the Author

Andy_L_J

Other

Australia Australia

Member
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.
 
Summer Soccer: http://www.pipekingsharkssummersoccer.com.au

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralMy vote of 1 PinmemberJecka1:03 16 Dec '09  
QuestionWhy is not this article erased from the Resource so far??? PinmemberJecka1:00 16 Dec '09  
This article containts a lot of wrong things listed in previous comments so I should not repeat it!
Author should read books for beginners first before making articles about such a theoretic question
GeneralPlease the correct the article or just scrp it if possible.,. It will misleads the begginers.,. PinmemberSrinath G Nath21:24 9 Dec '09  
GeneralPassing a reference ByRef is not the same as ByVal. Pinmembersupercat98:23 2 Dec '09  
GeneralThe only thing that should be ignored PinmemberTimMahy200312:34 1 Dec '09  
GeneralInaccurate. Pinmemberdequadin8:33 29 Nov '09  
GeneralRe: Inaccurate. PinmemberAndy_L_J19:11 29 Nov '09  
GeneralRe: Inaccurate. Pinmemberdequadin3:06 30 Nov '09  

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

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

Permalink | Advertise | Privacy | Mobile
Web04 | 2.5.120210.1 | Last Updated 20 Feb 2010
Article Copyright 2009 by Andy_L_J
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid