如何:防止过程参数的值被更改
更新:2007 年 11 月
如果过程将形参声明为 ByRef,则 Visual Basic 会为过程代码提供对调用代码中作为实参基础的编程元素的直接引用。这使得过程能够更改调用代码中作为实参基础的值。在某些情况下,调用代码可能要防止这种更改。
总是可以通过声明过程中的对应形参 ByVal 来防止实参更改。如果希望在某些情况下能够更改给定的实参而在其他情况下不可以,则可以按 ByRef 方式声明它,让调用代码确定每个调用中的传递机制。实现的方式是通过将对应的实参括在括号中而通过值传递,或是通过不将对应的实参括在括号中而通过引用传递。有关更多信息,请参见 如何:强制通过值传递参数。
示例
下面的示例演示使用数组变量作为形参并对数组元素进行操作的两个过程。increase 过程只是让每个元素加 1。replace 过程为形参 a() 分配一个新数组,然后让数组中的每个元素加 1。但是,重新分配并不会影响调用代码中的基础数组变量。
Public Sub increase(ByVal a() As Long)
For j As Integer = 0 To UBound(a)
a(j) = a(j) + 1
Next j
End Sub
Public Sub replace(ByVal a() As Long)
Dim k() As Long = {100, 200, 300}
a = k
For j As Integer = 0 To UBound(a)
a(j) = a(j) + 1
Next j
End Sub
Dim n() As Long = {10, 20, 30, 40}
Call increase(n)
MsgBox("After increase(n): " & CStr(n(0)) & ", " & _
CStr(n(1)) & ", " & CStr(n(2)) & ", " & CStr(n(3)))
Call replace(n)
MsgBox("After replace(n): " & CStr(n(0)) & ", " & _
CStr(n(1)) & ", " & CStr(n(2)) & ", " & CStr(n(3)))
第一个 MsgBox 调用显示“After increase(n): 11, 21, 31, 41”。因为数组 n 是一个引用类型,所以即使传递机制是 ByVal, replace 也可以更改其成员。
第二个 MsgBox 调用显示“After replace(n): 11, 21, 31, 41”。因为 n 的传递方式为 ByVal,所以 replace 不能通过给它分配新数组来修改调用代码中的变量 n 。当 replace 创建新的数组实例 k ,并将其赋给局部变量 a 时,它将丢失由调用代码传入的对 n 的引用。当它更改 a 的成员时,只影响局部数组 k 。因此, replace 不会在调用代码中增加数组 n 的值。
编译代码
Visual Basic 中的默认行为是通过值传递实参。不过,在声明每个形参时都使用关键字 ByVal 或 ByRef 是一种很好的编程习惯。这将增强代码的可读性。