Difference between ByVal and ByRef?
What is the difference? I always use ByVal, but,开发者_StackOverflow I don't really have a good idea of when should I and when not...
ByRef
= You give your friend your term paper (the original) he marks it up and can return it to you.
ByVal
= You give him 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 original 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, any changes made will be immediate and permanent. If the method fails, the object could be corrupted. Using ByVal will make a copy, pass the whole copy into the method, and then the method will process the info and either return a copy back, report information or do nothing.
If you pass in a reference, when you modify the value in the method, the variable in the call site will also be modified.
If you pass value, it's the same as if another variable is created at the method, so even if you modify it, the original variable (at the call site) won't have its value changed.
So, indeed, you should usually pass variables as value. Only pass as reference if you have an explicit need to do so.
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.
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.
I hope this answers your question
Sub last_column_process()
Dim last_column As Integer
last_column = 234
MsgBox last_column
trying_byref x:=last_column
MsgBox last_column
trying_byval v:=last_column
MsgBox last_column
End Sub
Sub trying_byref(ByRef x)
x = 345
End Sub
Sub trying_byval(ByRef v)
v = 555
End Sub
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
ByRef, one value will have 2 addresses
So if x=80 (80 is value and x is address, then for example variable y can be 80 as well, and thus 80 can be accessed by x and y)
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
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.
精彩评论