Difference between ByVal and ByRef?

后端 未结 9 2261
囚心锁ツ
囚心锁ツ 2020-12-15 19:34

What is the difference? I always use ByVal, but, I don\'t really have a good idea of when should I and when not...

相关标签:
9条回答
  • 2020-12-15 19:55

    Answers by @Tom and @kelloti are helpful. Here's a code example to illustrate further:

    Private Function ValMessage(ByVal SomeMessage As String)
        SomeMessage = "Val Val Val" ' <-- this variable modification doesn't persist after the function finishes execution
        ValMessage = "Some Return Value"
    End Function
    
    Private Function RefMessage(ByRef SomeMessage As String)
        SomeMessage = "Ref Ref Ref" ' <-- this variable modification persists even after the function finishes execution
        RefMessage = "Some Return Value"
    End Function
    
    Private Sub DoStuff()
        Dim OriginalMessage As String
        Dim OtherMessage As String
        Dim AnotherMessage As String
    
        OriginalMessage = "Original"
        MsgBox ("ORIGINAL: " & OriginalMessage) '--> "Original"
    
        OtherMessage = ValMessage(OriginalMessage)
        MsgBox ("ORIGINAL: " & OriginalMessage) '--> "Original"
    
        AnotherMessage = RefMessage(OriginalMessage)
        MsgBox ("ORIGINAL: " & OriginalMessage) '--> "Ref Ref Ref" <--- this is the difference when you pass a paramter by reference
    End Sub
    
    0 讨论(0)
  • 2020-12-15 19:57

    ByRef = You give your friend your term paper (the original) he marks it up and can return it to you.

    ByVal = You give hime a copy of the term paper and he give you back his changes but you have to put them back in your original yourself.

    As simple as I can make it.

    Why to use Byref:
    ByRef will pass the POINTER to the object you are passing. If you are in the same memory space, this means passing just the 'word' not the object. The method you are passing it to can make changes in the origuinal object, and does not need to pass them back at all, as they are in the original object. Useful for making large data passes faster. You can also use ByRef to allow use of a SUB rather then a FUNCTION (In VB) since it does not need to pass back the object.

    Why Not to Use Byref:
    Since the method has access to the original, anychanges made will be immediate and permanent. If the method fails, the oblect could be corrupted. Using ByVal will make a copy, pass the whole copy into the method, and then the metod will process the info and either retunr a copy back, report information or do nothing.

    0 讨论(0)
  • 2020-12-15 20:00

    ByRef is like a second return value. It passes a reference to the object into the function rather than the object itself. If you change the value of a ByRef parameter in the function, you will see those changes after the function ends. If that wasn't clear enough, read this and this.

    0 讨论(0)
  • 2020-12-15 20:00

    I know this question has pretty much been answered, but I just wanted to add the following...

    The object you pass to a function is subject to ByRef/ByVal, however, if that object contains references to other objects, they can be modified by the called method regardless of ByRef/ByVal. Poor explanation, I know, see code below for a better understanding:

    Public Sub Test()
        Dim testCase As List(Of String) = GetNewList()
        ByRefChange1(testCase)
        'testCase = Nothing
        testCase = GetNewList()
    
        ByValChange1(testCase)
        'testCase is unchanged
        testCase = GetNewList()
    
        ByRefChange2(testCase)
        'testCase contains the element "ByRef Change 2"
        testCase = GetNewList()
    
        ByValChange2(testCase)
        'testCase contains the element "ByVal Change 2"
    
    End Sub
    
    Public Function GetNewList() As List(Of String)
        Dim result As List(Of String) = New List(Of String)
        result.Add("Value A")
        result.Add("Value B")
        result.Add("Value C")
        Return result
    End Function
    
    Public Sub ByRefChange1(ByRef aList As List(Of String))
        aList = Nothing
    End Sub
    
    Public Sub ByValChange1(ByVal aList As List(Of String))
        aList = Nothing
    End Sub
    
    Public Sub ByRefChange2(ByRef aList As List(Of String))
        aList.Add("ByRef Change 2")
    End Sub
    
    Public Sub ByValChange2(ByVal aList As List(Of String))
        aList.Add("ByVal Change 2")
    End Sub
    

    EDIT:

    Also, consider if this function was called:

    Public Sub ByValChange3(ByVal aList As List(Of String))
        aList.Add("ByVal Change 3")
        aList = New List(Of String)
        aList.Add("ByVal Change 4")
    End Sub
    

    What happens in this case is "ByVal Change 3" is added to the callers list, but at the point you specify that "aList = New List" you are then pointing the new reference, to a new object, and become detached from the callers list. Both common sense and might catch you out one day, so something to bear in mind.

    0 讨论(0)
  • 2020-12-15 20:02

    I will try to explain the difference in simple words.

    • passing argument by value makes it input only parameter. This is the safest way, therefore is used by default in 95% of the cases.

    • passing argument by reference makes it both input and output parameter. The output parameter can be changed inside the function which creates a rarely used side-effect.

    0 讨论(0)
  • 2020-12-15 20:06

    Think there may have been a typo in the last sample: The last sub should be "byval" and not "byref". :)

    Also added a msgbox statement in trying_byval so you can understand what is meant.

    Sub begin()
    Dim last_column As Integer
    
    last_column = 234
    MsgBox "Begin:" & last_column
    
    trying_byref x:=last_column
    MsgBox "byref:" & last_column
    
    trying_byval v:=last_column
    MsgBox "byval:" & last_column
    End Sub
    
    Sub trying_byref(ByRef x)
    x = 111
    End Sub
    
    Sub trying_byval(ByVal v)  '<--not ByRef, that was in sub trying_byref.
    v = 222
    MsgBox "In Here:" & v
    End Sub
    
    0 讨论(0)
提交回复
热议问题