有什么不同?我总是使用 ByVal,但是,我真的不知道什么时候应该什么时候不应该......
9 回答
ByRef
= 你给你的朋友你的学期论文(原件),他会做标记并可以退还给你。
ByVal
= 你给他一份学期论文,他把他的修改还给你,但你必须自己把它们放回原件。
尽可能简单。
为什么要使用 ByRef:
ByRef 会将 POINTER 传递给您要传递的对象。如果您在同一个内存空间中,这意味着只传递“单词”而不是对象。您传递给它的方法可以在原始对象中进行更改,并且根本不需要将它们传递回来,因为它们在原始对象中。有助于加快大数据传递。您还可以使用 ByRef 来允许使用 SUB 而不是 FUNCTION(在 VB 中),因为它不需要传回对象。
为什么不使用 ByRef:
由于该方法可以访问原始方法,因此所做的任何更改都将是即时且永久的。如果该方法失败,则该对象可能已损坏。使用 ByVal 将制作一个副本,将整个副本传递给该方法,然后该方法将处理信息并返回一个副本,报告信息或什么都不做。
如果传入一个引用,当你修改方法中的值时,调用站点中的变量也会被修改。
如果您传递值,则与在方法中创建另一个变量相同,因此即使您修改它,原始变量(在调用站点)的值也不会改变。
因此,实际上,您通常应该将变量作为值传递。如果您有明确的需要,请仅作为参考传递。
我知道这个问题已经得到了很好的回答,但我只想添加以下内容......
传递给函数的对象受 ByRef/ByVal 的约束,但是,如果该对象包含对其他对象的引用,则它们可以被调用的方法修改,而不管 ByRef/ByVal 是什么。我知道,解释不好,请参阅下面的代码以更好地理解:
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
编辑:
另外,请考虑是否调用了此函数:
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
在这种情况下发生的情况是将“ByVal Change 3”添加到调用者列表中,但是在您指定“aList = New List”时,您将新引用指向一个新对象,并与调用者分离列表。既是常识,也可能有一天会抓住你,所以要记住一些事情。
我希望这回答了你的问题
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
认为最后一个示例中可能有错字:最后一个子应该是“byval”而不是“byref”。:)
还在try_byval 中添加了一个msgbox 语句,以便您了解其含义。
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,一个值将有 2 个地址
因此,如果 x=80(80 是值,x 是地址,那么例如变量 y 也可以是 80,因此 x 和 y 可以访问 80)
@Tom 和 @kelloti 的回答很有帮助。下面是一个代码示例来进一步说明:
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
我将尝试用简单的语言解释差异。
按值传递参数使其仅输入参数。这是最安全的方式,因此在 95% 的情况下默认使用。
通过引用传递参数使其既是输入参数又是输出参数。可以在函数内部更改输出参数,这会产生很少使用的副作用。