ByVal和ByRef

摘自:https://www.cnblogs.com/mq0036/p/4236266.html

VBA中默认使用ByRef。ByVal的意思是按值传递参数,因为是按值传递,这个参数在过程里面的值有变化的话它影响的范围只是在这个过程里面。出了过程就没有用了。而ByRef是按地址或者说按引用传递,传递给过程的实际是这个数值的地址,而不是值本身,在过程中对改变这个参数也就是改变这个地址的值,这样在过程外面也可以看到这个值被改变了。运行下面的例子可以看到其中的区别。

Sub mmm(ByVal iI1 As Integer, iI2 As Integer)
iI1 = iI1 + 10
iI2 = iI2 + 10
MsgBox "Inside: iI1=" & iI1 & " iI2=" & iI2
End Sub
Sub mySub()
Dim iI1 As Integer
Dim iI2 As Integer
iI1 = 10
iI2 = 12
MsgBox "Before: iI1=" & iI1 & " iI2=" & iI2
Call mmm(iI1, iI2)
MsgBox "After: iI1=" & iI1 & " iI2=" & iI2
' 按顺序分别显示
    ' 显示 Before: iI1=10 iI2=12
    ' 显示 Before: iI1=20 iI2=22
    ' 显示 Before: iI1=10 iI2=22
    ' 过程mmm中修改了iI1和iI2,但是iI1是按值传递,在mmm过程之外的iI1并受影响
    ' 而iI2是按引用传递,mmm过程之外的iI2也被改变了
End Sub

另外,如果参数是数组的话,只能使用按引用传递,因为传递的实际上是数组第一个元素的地址。例如下面代码的用法。

Sub GetArray(arrTemp() As Integer)
Dim i As Integer
For i = 0 To UBound(arrTemp)
Debug.Print "Item " & i & ": " & arrTemp(i)
Next i
End Sub
Sub PassArray()
Dim arrInt(3) As Integer
arrInt(0) = 1
arrInt(1) = 2
arrInt(2) = 3
arrInt(3) = 4
Call GetArray(arrInt)
' 在立即窗口打印出
	' Item 0: 1
	' Item 1: 2
	' Item 2: 3
	' Item 3: 4
End Sub

但对于对象来说,使用ByVal实际上传递的仍然是对对象的引用,这样在过程中对象的修改将会影响过程外部对象的值或属性。如果使用ByVal,而在过程中创建一个新的对象实例,将该对象赋值给传递的对象,则不影响调用对象的外部的属性或值。而如果使用ByRef,在过程中创建一个新的对象实例,将该对象赋给传递的对象,却会影响过程外该对象的属性或值。

Sub TestByValByRef()
Dim objDic As Object
 
Set objDic = CreateObject("Scripting.Dictionary")
objDic(1) = 100
Debug.Print "byValueTest1"
Debug.Print "原始值: objDic(1)=" & objDic(1)
Call byValTest1(objDic)
Debug.Print "外部值: objDic(1)=" & objDic(1) & vbCrLf
 
objDic(1) = 100
Debug.Print "byValueTest2"
Debug.Print "原始值: objDic(1)=" & objDic(1)
Call byValTest2(objDic)
Debug.Print "外部值: objDic(1)=" & objDic(1) & vbCrLf
 
objDic(1) = 100
Debug.Print "byRefTest"
Debug.Print "原始值: objDic(1)=" & objDic(1)
Call byRefTest(objDic)
Debug.Print "外部值: objDic(1)=" & objDic(1)
End Sub
Private Sub byValTest1(ByVal c As Object)
Dim a As Object
Set a = CreateObject("Scripting.Dictionary")
a(1) = 200
Set c = a
End Sub
Private Sub byValTest2(ByVal c As Object)
c(1) = 200
End Sub
Private Sub byRefTest(ByRef c As Object)
Dim a As Object
Set a = CreateObject("Scripting.Dictionary")
a(1) = 200
Set c = a
End Sub

运行过程TestByValByRef,将在立即窗口打印出下面的结果。

byValueTest1
原始值: objDic(1)=100
外部值: objDic(1)=100

byValueTest2
原始值: objDic(1)=100
外部值: objDic(1)=200

byRefTest
原始值: objDic(1)=100
外部值: objDic(1)=200

posted @ 2021-07-03 15:04  NAMEISFUCK  阅读(535)  评论(0)    收藏  举报