VBA数组函数将具有简单类型的变量转换为值,并且不存储变量引用

时间:2019-12-05 19:33:06

标签: arrays vba collections

VBA数组函数将简单类型的变量转换为值,并且不存储变量引用。但是,如果我传递一个类变量,它将按预期工作。应该是那样的还是我错过了什么?

主模块

Sub test()

Dim collection As collection
Set collection = New collection

Dim i As Long
Dim cl As New tst

i = 25
cl.i = 25

Debug.Print "Original i = " & i
Debug.Print "Original cl.i = " & cl.i
Debug.Print

collection.Add Item:=Array(i)
collection.Add Item:=Array(cl)

Debug.Print "i in array in collection: collection(1)(0) = " & collection(1)(0)
Debug.Print "i from class in array in collection: collection(2)(0).i = " & collection(2)(0).i
Debug.Print

i = i + 1
cl.i = cl.i + 1

Debug.Print "Adding: i = i + 1"
Debug.Print

Debug.Print "Original i = " & i ' 26
Debug.Print "Original cl.i = " & cl.i '26
Debug.Print

Debug.Print "i in array in collection: collection(1)(0) = " & collection(1)(0) '25, but I expect 26
Debug.Print "i from class in array in collection: collection(2)(0).i = " & collection(2)(0).i '26 correct
Debug.Print

End Sub

tst类

Public i As Long

输出

Original i = 25
Original cl.i = 25

i in array in collection: collection(1)(0) = 25
i from class in array in collection: collection(2)(0).i = 25

Adding: i = i + 1

Original i = 26
Original cl.i = 26

i in array in collection: collection(1)(0) = 25
i from class in array in collection: collection(2)(0).i = 26

1 个答案:

答案 0 :(得分:4)

  

是不是应该这样

当然。而且,无论您要传递值还是对象引用,其行为都完全相同。

i添加到集合时,会将ByVali)的副本 集合;递增i不会递增副本。

当您向集合中添加cl时,该对象的指针(也为ByVal)的副本 ;修改该指针也不会修改集合中的副本:

Public Sub test()
    Dim c As Collection
    Set c = New Collection
    Dim o As Class1
    Set o = New Class1
    Debug.Print VarPtr(o), ObjPtr(o)
    c.Add o
    Debug.Print VarPtr(c(1)), ObjPtr(c(1))
End Sub

此代码输出如下内容:

 725937672     221317072 
 725937528     221317072 

请注意,两个指针不同,但是都指向相同的对象引用。

如果我们在本地影响该对象指针的本地副本...

Debug.Print VarPtr(o), ObjPtr(o)
c.Add o
Set o = Nothing
Debug.Print VarPtr(c(1)), ObjPtr(c(1))
Debug.Print VarPtr(o), ObjPtr(o)

现在输出如下:

 725937672     221317072 
 725937528     221317072 
 725937672     0 

我们将o重新分配给Nothing,但是集合c still 引用了该对象!我们根本不影响物体!

您的测试类的Public i成员从未被复制到任何地方,该集合甚至都不知道/不在乎:所有集合都知道,它持有对对象的引用。

因此,当您执行cl.i = 26时,就不会分配该集合所知道的任何内容。您只是在说“将对象移到地址X(集合中保存的相同ObjPtr !,获取其i属性,并为其赋值26”:该集合的指针副本)从未更新过。

当您执行i = 26时,您并没有分配该集合所知道的任何信息。您说的是“在地址X(局部变量)处获取变量,为其分配值26”:该值的集合副本从未更新。