类模块类型的数组不更新 [英] Array of Class Module type not updating
问题描述
这是一个数据类模块,名为Class_E
公共名称作为变式
公共年龄作为变式
这是身体代码,它只是分配和重新分配值到2个数组
Sub main()
Dim r As Class_E
设置r = Band()
End Sub
功能带( )As Class_E
Set Band = New Class_E
'第1部分:初始化变量
Debug.PrintPart 1
Band.Name = Array(Edison ,特斯拉,法拉第,图灵)
Debug.PrintBefore:Name = {& Band.Name(0)& ,& Band.Name(1)& ,& Band.Name(2)& ,& Band.Name(3)& }
Band.Age = Array(10,10,10,10)
Debug.Print之前:Age = {& Band.Age(0)& ,&乐队(1)& ,& Band.Age(2)& ,& Band.Age(3)& }
'第2部分:按项目
更改数组的值Debug.Print第2部分
对于k = LBound(Band.Name)到UBound(Band .Name)
Debug.Printk =& k
Band.Name(k)=Foo
Band.Age(k)= 999
下一步k
Debug.Print之后:Name = {& Band.Name(0)& ,& Band.Name(1)& ,& Band.Name(2)& ,& Band.Name(3)& }
Debug.Print之后:Age = {& Band.Age(0)& &乐队(1)& & Band.Age(2)& & Band.Age(3)& $
第3部分:更改数组的值,完全
Debug.PrintPart 3
Band.Name = Array(Spring,Summer 秋,冬)
Debug.Print再次:Name = {& Band.Name(0)& ,& Band.Name(1)& ,& Band.Name(2)& ,& Band.Name(3)& }
Band.Age = Array(11,11,11,11)
Debug.Print再次:Age = {& Band.Age(0)& ,&乐队(1)& ,& Band.Age(2)& ,& Band.Age(3)& }
'第4部分:使用另一个temp数组变量
Debug.PrintPart 4
Dim Temp_Name As Variant,Temp_Age As Variant
Temp_Name = Band对于k = LBound(Band.Name)到UBound(Band.Name)
Debug.Printk =& k
Temp_Name(k)=Foo
Temp_Age(k)= 999
下一步k
Debug.PrintTemp:Name = {& Temp_Name(0)& ,& Temp_Name(1)& ,& Temp_Name(2)& ,& Temp_Name(3)& }
Debug.PrintTemp:Age = {& Temp_Age(0)& & Temp_Age(1)& & Temp_Age(2)& & Temp_Age(3)& }
'第5部分:再次使用原始数组
Debug.Print第5部分
Debug.Print再次:Name = {& Band.Name(0)& ,& Band.Name(1)& ,& Band.Name(2)& ,& Band.Name(3)& }
Debug.Print再次:Age = {& Band.Age(0)& ,&乐队(1)& ,& Band.Age(2)& ,& Band.Age(3)& }
结束函数
这是我的输出屏幕得到
第1部分
之前:Name = {爱迪生,特斯拉,法拉第,图灵}
之前:年龄= {10,10,10,10}
第2部分
k = 0
k = 1
k = 2
k = 3
之后:Name = Edison,特斯拉,法拉第,图灵}
之后:年龄= {10 10 10 10}
第3部分
再次:Name = {Spring,Summer,Autumn,Winter}
再次:年龄= {11,11,11,11}
第4部分
k = 0
k = 1
k = 2
k = 3
温度: {Foo,Foo,Foo,Foo}
温度:年龄= {999 999 999 999}
第5部分
再次:Name = {Spring,Summer,Autumn,Winter}
再次:年龄= {11,11,11,11}
问题:
1.为什么第2部分中的简单作业没有执行?并且没有错误消息。我们没有问题重新分配数组,如第3部分所示。
2.为什么Temp_Name = Band.Name在第4部分是数组值的副本而不是数组指针?没有关于临时数组的内存分配的指令。
您的输入受到高度评价。
使用数组作为公共类成员是有问题的。有一个原因VBA不允许它。您尝试通过将成员声明为 Variant
来解决此限制,但这并不能解决问题。
您可以使用 Collection
s或 Dictionary
s,因为这些是对象
所以你可以设置
参考。但VBA数组是价值类型。因此,当您从函数获取数组时,您将获得阵列的复制。
- 为什么第2部分中的简单作业没有执行?并且没有错误消息。我们没有问题重新分配数组,如第3部分所示。
因为你实际工作在数组的复制上。在
Band.Name(k)=Foo
尽管 Band.Name
似乎直接访问类的一个字段,它实际上是通过一个属性获取wrapper;这是公共类成员的情况,编译器自动添加COM的IDispatch接口所需的get / let包装器和最终的后期绑定(访问对象
引用中的类) 。包装器返回数组的复制,不是引用,因为如前所述,VBA中的数组(和Strings)是值类型,而不是对象。所以yoiu在数组的副本上工作。
您可以通过添加 Property Let
成员数组中的条目。考虑这个代码为你的课程:
公共名称作为变量'< - 更改为复数以添加属性get / let
公共年龄作为变量'< - 相同
公共属性让名字(我作为长字符串)
名称(i)= s
结束属性
公共财产让年龄(我长,val长)
年龄(i)= val
结束属性
您可以使用这些来分配成员数组中的条目。您的Part2将按预期工作。
- 为什么Temp_Name = Band.Name在第4部分中是数组值而不是数组指针的副本?没有关于临时数组的内存分配的指令。
如前所述,数组是值 - 类型,而不是对象。将数组分配给变量总是创建一个复制,不要像对象案例一样重复引用。 (添加到包装器属性,你发现自己距离初始类的数组两英里)。
I've struck my foot against some weird arrays, to which i can assign value to the whole array but not individual array members.
This is a data class module, named Class_E
Public Name As Variant
Public Age As Variant
and this is the body code, which just assigns and re-assigns values to 2 arrays
Sub main()
Dim r As Class_E
Set r = Band()
End Sub
Function Band() As Class_E
Set Band = New Class_E
'Part 1: Initialize the variables
Debug.Print "Part 1"
Band.Name = Array("Edison", "Tesla", "Faraday", "Turing")
Debug.Print "Before: Name={" & Band.Name(0) & ", " & Band.Name(1) & ", " & Band.Name(2) & ", " & Band.Name(3) & "}"
Band.Age = Array(10, 10, 10, 10)
Debug.Print "Before: Age={" & Band.Age(0) & ", " & Band.Age(1) & ", " & Band.Age(2) & ", " & Band.Age(3) & "}"
'Part 2: Change values of arrays, by item
Debug.Print "Part 2"
For k = LBound(Band.Name) To UBound(Band.Name)
Debug.Print "k=" & k
Band.Name(k) = "Foo"
Band.Age(k) = 999
Next k
Debug.Print "After: Name={" & Band.Name(0) & ", " & Band.Name(1) & ", " & Band.Name(2) & ", " & Band.Name(3) & "}"
Debug.Print "After: Age={" & Band.Age(0) & " " & Band.Age(1) & " " & Band.Age(2) & " " & Band.Age(3) & "}"
'Part 3: Change values of array, entirely
Debug.Print "Part 3"
Band.Name = Array("Spring", "Summer", "Autumn", "Winter")
Debug.Print "Again: Name={" & Band.Name(0) & ", " & Band.Name(1) & ", " & Band.Name(2) & ", " & Band.Name(3) & "}"
Band.Age = Array(11, 11, 11, 11)
Debug.Print "Again: Age={" & Band.Age(0) & ", " & Band.Age(1) & ", " & Band.Age(2) & ", " & Band.Age(3) & "}"
'Part 4: Use another temp array variable
Debug.Print "Part 4"
Dim Temp_Name As Variant, Temp_Age As Variant
Temp_Name = Band.Name
Temp_Age = Band.Age
For k = LBound(Band.Name) To UBound(Band.Name)
Debug.Print "k=" & k
Temp_Name(k) = "Foo"
Temp_Age(k) = 999
Next k
Debug.Print "Temp: Name={" & Temp_Name(0) & ", " & Temp_Name(1) & ", " & Temp_Name(2) & ", " & Temp_Name(3) & "}"
Debug.Print "Temp: Age={" & Temp_Age(0) & " " & Temp_Age(1) & " " & Temp_Age(2) & " " & Temp_Age(3) & "}"
'Part 5: Original arrays again
Debug.Print "Part 5"
Debug.Print "Again: Name={" & Band.Name(0) & ", " & Band.Name(1) & ", " & Band.Name(2) & ", " & Band.Name(3) & "}"
Debug.Print "Again: Age={" & Band.Age(0) & ", " & Band.Age(1) & ", " & Band.Age(2) & ", " & Band.Age(3) & "}"
End Function
This is the output screen I've got
Part 1
Before: Name={Edison, Tesla, Faraday, Turing}
Before: Age={10, 10, 10, 10}
Part 2
k=0
k=1
k=2
k=3
After: Name={Edison, Tesla, Faraday, Turing}
After: Age={10 10 10 10}
Part 3
Again: Name={Spring, Summer, Autumn, Winter}
Again: Age={11, 11, 11, 11}
Part 4
k=0
k=1
k=2
k=3
Temp: Name={Foo, Foo, Foo, Foo}
Temp: Age={999 999 999 999}
Part 5
Again: Name={Spring, Summer, Autumn, Winter}
Again: Age={11, 11, 11, 11}
Questions:
1. Why are the simple assignments in Part 2 not executed ? and there is no error message. we have no problem re-assigning the arrays as shown in Part 3.
2. Why "Temp_Name = Band.Name" in Part 4 a copy of array values instead of the array pointer ? There is no instruction for memory allocation to the temporary arrays.
Your inputs are highly appreciated.
Using arrays as public class members is problematic. There's a reason why VBA does not allow it. You tried to overcome this restriction by declaring the members as Variant
, but this does not solve the problem.
You can possibly use Collection
s or Dictionary
s, because these are Objects
so you can Set
references on them. But VBA Arrays are Value-types. Hence when you get an array from a function, you will get a copy of the array.
- Why are the simple assignments in Part 2 not executed ? and there is no error message. we have no problem re-assigning the arrays as shown in Part 3.
Because you actually worked on a copy of the array. In the statement
Band.Name(k) = "Foo"
Although Band.Name
seems to access directly a field of the class, it is actually accessing it through a property get "wrapper"; this is always the case with public class members, the compiler automatically adds get/let wrappers needed for COM's IDispatch interface and eventual late-binding (accessing the class in an object
reference). The wrapper returns a copy of the array, not a reference, because as stated earlier, Arrays in VBA (and Strings for that matter) are value-types, not objects. So yoiu worked on the copy of the array.
You can overcome this problem by adding Property Let
methods that assign entries in the member array. Consider this code for your class:
Public Names As Variant '<-- Change to plural to add property get/let
Public Ages As Variant ' <-- Same
Public Property Let Name(i As Long, s As String)
Names(i) = s
End Property
Public Property Let Age(i As Long, val As Long)
Ages(i) = val
End Property
You can use these to assign entries in the member arrays. Your Part2 will then work as expected.
- Why "Temp_Name = Band.Name" in Part 4 a copy of array values instead of the array pointer? There is no instruction for memory allocation to the temporary arrays.
As stated earlier, arrays are value-types, not objects. Assigning an array to a variable always creates a copy, never a duplicate reference like the object case. (add to that the wrapper property get and you find yourself two miles away from the initial class's array).
这篇关于类模块类型的数组不更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!