Results 1 to 5 of 5

Thread: ByVal vs ByRef, and Value types vs Reference types

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    ByVal vs ByRef, and Value types vs Reference types

    Hey,

    This is an 'article' about two concepts:
    • Passing arguments ByVal or ByRef
    • Value types vs Reference types


    Since this seems to be a common source of issues for both beginners and more experienced VB.NET programmers, I decided to write a little codebank article on it. This is aimed primarily at the beginners, and the details may not be absolutely correct. I simplified some concepts to make it easier to understand, so beginners can use the concepts correctly without having to know everything about memory management in .NET

    A little disclaimer: I don't pretend to know everything about the subject, but hopefully enough to write this article. If I have something wrong, please feel free to correct me




    Passing arguments ByVal or ByRef

    In VB.NET, every argument that a method takes is preceded by either the ByVal (which is the default) or ByRef keyword. Which keyword you use decides how VB will handle the object you pass as the argument when you call the method.
    Code:
    Private Sub Sum(ByVal x As Integer, ByVal y As Integer)
       Dim result As Integer = x + y
       MessageBox.Show(result.ToString)
    End Sub
    The keyword ByVal stands for 'by value'. It tells VB that the value passed into this argument should be passed 'by value'. In other words, VB makes a local copy of the object, one that is completely separate from the object you pass into the method.

    Because of this, any change you make to an argument passed by value will not persist beyond that method. A simple example:
    Code:
    Private Sub ByValMethod(ByVal x As Integer)
       x = 5
    End Sub
    If you call this method, passing some value for x (let's say 3), then that value will still be 3 after the method, and not 5!
    Code:
    Dim value As Integer = 3
    ByValMethod(value)
    MessageBox.Show(value.ToString)
    The message box will show "3", and not "5", even though you explicitly set the argument 'x' to 5 in the method ByValMethod!

    Why does this happen? It's very simple: the variable 'x', the argument, is a local copy of the variable that is passed to the method ('value'). A local copy is made, and that copy gets the same value (3). Then, you change the value of the local copy to 5, but you never touch the original variable, and the variable 'value' will remain 3. The local copy, now equal to 5, is 'lost' after the ByValMethod method is done (the variable goes "out of scope" and its value is gone).



    So, what do you do if you do want the original variable to be changed? You use ByRef!

    ByRef stands for 'by reference'. It tells VB that the argument passed to a function is to be passed by its reference.
    You must understand that every variable in VB is located somewhere in the computer's memory. For example, the value of the variable 'value' in the code sample above could, possibly, be stored at memory location 12385 (or something). VB will simply tell the computer to look up the value at memory location 12385, and it will see that the memory contains the value 3.

    When you pass an argument by reference, VB actually passes this memory location to the method.
    Let's consider the same method as before, but now we pass the argument by reference:
    Code:
    Private Sub ByRefMethod(ByRef x As Integer)
       x = 5
    End Sub
    The variable 'x' now points to the same memory location of the object that you pass into this method.

    So, if we use the same code as before, except we now call the ByRefMethod,
    Code:
    Dim value As Integer = 3
    ByRefMethod(value)
    MessageBox.Show(value.ToString)
    the variable 'x' in the method ByRefMethod now points to the same memory location as the variable 'value'.

    So, the method will set the value of that memory location to 5, and the value of the variable 'value' is actually changed to 5 this time! The message box will thus show "5", as you might have expected it would always do.

    So, in short: when you want to change the value of an argument inside a method, that argument must be passed by reference (ByRef), because otherwise you are only changing a local copy of the variable, which won't do you any good outside of the method it lives in.



    However! There is an important "but" here. Before I explain what it is though, you need to understand the difference between reference types and value types, so read on to the next post!

  2. #2

    Thread Starter
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Re: ByVal vs ByRef, and Value types vs Reference types

    Value types vs Reference types

    If you've ever read anything about value types or reference types, the most common thing you will probably have read is that value types are stored on the stack, while reference types are stored on the heap.
    What does this tell you? Well, nothing really. Unless you are interested in the inner workings of .NET, this information is quite useless to you.

    The difference between value types and reference types, in the most basic form, is that value types hold their data directly, while reference types point to a location in memory, and the data is located in that memory.

    First of all, which types are value types and which types are reference types? The short answer is that all structures are value types, and all classes are reference types. This automatically means that all Controls, Forms, etc, which are classes, are reference types. It also means that objects like a Point, Rectangle, Integer, are value types.

    You can also remember that most 'primitive' types (think all numerical types such as Integer, Single, Double, Decimal, but also Boolean, Char, etc) are value types.

    If you ever need to find out whether a type is a class (reference type) or structure (value type), you can look it up on MSDN, or you can simply use it in a (valid) expression in the VB editor and hover your mouse over it (over the type name!). The Intellisense tooltip will tell you whether it is a class or a structure.



    If you use the data of a value type, VB is simply making you use the actual data that this object holds.
    If you use the data of a reference type, VB first has to make your computer look in the memory, at the memory location specified by the data that the reference type contains. It has to read the memory to find out what data it actually is.

    For example, if you use an Integer variable, which is a value type, that variable holds the actual value of the integer (3, or 5, or any other integer).
    If you use a Form variable, which is a reference type, that variable only holds the memory location at which the computer can find the relevant data for the form.

    Here is an 'artist impression' of how you can imagine it:

    The value type holds the value "3" directly, while the reference type holds the value "12385", which is a pointer to some data in the memory. That data in the memory (represented by binary 010101 data in the picture) represents the actual value of the reference type.



    "Why is this relevant", or "what do I need to know this for?", I hear you ask.
    The answer is related to passing arguments by value or by reference, as discussed above.

    I told you that arguments passed by value (ByVal) only exist as a local copy in that method, so that any changes you make to that copy are not persisted outside of the method.

    While that is still true, for reference types it does not work quite as literally as you may think (it does apply to value types at all times).

    Remember what the value of a reference type represented? A location in memory (let's say 12385 again). What happens if you make a copy of this memory location?
    A copy of '12385' is again '12385', which is the same memory location!

    So while VB actually does make a copy of the value, that value is only the memory location for a reference type, and the actual data on that memory location is not copied elsewhere. So, when you make a change to a reference type, even when passed ByVal, you are changing the data that is stored on the memory location given by the copy of the value of the reference type. Since the copy of the value of the reference type is just the same memory location, you are actually accessing the same data!

    This is the crucial point. You are accessing the same data, regardless of whether you pass the argument ByVal or ByRef. So, whenever you pass a reference type by value (or by reference of course), you can change it!


    Here is another artist impression, this time showing you what happens when you pass a value to a method (ByVal) and then change it:

    In the case of the value type, a copy of the value 3 is made, and then changed into 5, while the original value is still 3.
    For a reference type however, a copy of the memory location is made, so the copy points to the same data. When you change the data present at the memory location given by the reference type, you are changing the actual data (represented in red), even though you are modifying 'a copy' of the variable!



    So, what you need to keep in mind is that, when passing reference types, it does not matter whether you use ByVal or ByRef. Both ways allow you to change the argument!

    There is only one slight difference between ByVal and ByRef in the case of reference types: for ByVal arguments, you cannot assign a new instance of that type. Well, you can try, but it will not work.

    Example:
    Code:
        Private Sub Abc(By(Val/Ref) x As ListBox)
            x = New ListBox
        End Sub
    As you can see, this method accepts a ListBox (ByVal or ByRef, I will explain both methods).
    If we use this method on an existing ListBox that we put some values in, we get different behavior whether we pass it ByVal or ByRef:
    Code:
            Dim l As New ListBox
            l.Items.Add(1)
            l.Items.Add(2)
            l.Items.Add(3)
            Abc(l)
            Me.Controls.Add(l)
    If we pass the listbox by reference (ByRef), the form shows an empty listbox. This is to be expected: you pass the listbox, with some items in it, to the Abc method, which assigns a new instance fo the variable holding that listbox. The new instance of the listbox obviously does not contain any items (yet), so the control we finally place on the form is empty.

    If, however, we pass the listbox by value (ByVal), the listbox does keep its items! Even though we can modify the ListBox (give it a different color, or even add some items), we cannot assign a new instance to the variable. It simply does not work (but it does not give you any errors, so this is something to keep in mind!).


    Well, that's it at least for now! I hope this is useful for someone. At least I'll have something to point to whenever this question pops up again

  3. #3
    Pro Grammar chris128's Avatar
    Join Date
    Jun 2007
    Location
    England
    Posts
    7,604

    Re: ByVal vs ByRef, and Value types vs Reference types

    At least I'll have something to point to whenever this question pops up again
    I only just remembered that you had posted this after typing out my own brief summary in a thread in the VB.NET forum (http://www.vbforums.com/showthread.php?t=613254) so I've amended it to point to this thread as well
    My free .NET Windows API library (Version 2.2 Released 12/06/2011)

    Blog: cjwdev.wordpress.com
    Web: www.cjwdev.co.uk


  4. #4
    Frenzied Member obi1kenobi's Avatar
    Join Date
    Aug 2007
    Posts
    1,091

    Re: ByVal vs ByRef, and Value types vs Reference types

    Terrific tutorial, my hat's off to you
    Please rate helpful ppl's posts. It's the best 'thank you' you can give

  5. #5
    Registered User
    Join Date
    Jan 2018
    Posts
    1

    Re: ByVal vs ByRef, and Value types vs Reference types

    need for it now

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width