类模块类型的数组不更新 [英] Array of Class Module type not updating

查看:136
本文介绍了类模块类型的数组不更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我碰到了一些奇怪的数组,我可以为这个数组赋值,而不是单个的数组成员。



这是一个数据类模块,名为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数组是价值类型。因此,当您从函数获取数组时,您将获得阵列的复制



  1. 为什么第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将按预期工作。



  1. 为什么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 Collections or Dictionarys, 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.

  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.

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.

  1. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆