忘了之前有没有碰到过这样的问题先描述下问题,使用字典对象中再存放数组目的是为了
1.使用字典对象中元素可以通过KEY值索引,而不是数组的数字索引值。
2.字典对象中存放字典对象当然没错,从开销方面考虑,改用存放数组但存放数组后,无法改变这个字典对象中数组的值,变成了只读形式,很纳闷,还请指教下解决方法和这个问题的本质是什么。
VB代码
Dim test As New Scripting.Dictionary
Dim b(1) As Integer
b(0) = 100
b(1) = 20
test.Add "a1", b 
MsgBox (test.Item("a1")(1))       ‘显示20没有错test.Item("a1")(1) = 444
MsgBox (test.Item("a1")(1))       '期望是444,但实际显示的还是20

解决方案 »

  1.   

    b(1)=444
    test("a1")=b
    msgbox test("a1")(1)
      

  2.   

    楼上的方法可以解决直接赋值导致无效的问题
    不过并不艺术,因为实际应用中我会把这个字典对象以传址的方式传递给别的函数或者方法,此时b数组应该是被垃圾回收处理掉了,所以传递给的函数或者方法中无法直接写
    b(1)=444
    而是必须在声明一个零时数组变量 比如
    dim c(1) as integer
    然后还要
    c(0) = test.item("a1")(0)
    c(1)=444
    test.item("a1")=c
    但在数组的元素量比较多的时候就会很麻烦。当然是一种解决方法,所以我说不艺术就在于此。更多的想知道引起这个问题的原因,把握本质后或者方法就自然而然想到了。
    是字典对象的元素如果是非直接量的数值时,都是存储地址的关系吗,但也说不通引用后无法给其赋值的情况,似乎更应该是
    test.item("a1")(...)这个写法的问题。
      

  3.   

    你试试这样:
    ''.....
    dim c
    c=test("a1")
    c(1)=444
    test("a1")=c
    msgbox test("a1")(1)
    '''......
      

  4.   

    谢谢楼上的回复 不过
    亲 很抱歉 只能说你的代码没测试过
    显示值依然是赋值之前的原值 
    下面把测试代码发出来Private Sub Form_Load()
        Dim mydic As New Scripting.Dictionary
        Set mydic = test()
        MsgBox (mydic.Item("ok")(1))  ‘这里显示原值2没错
        
        Dim cc
        cc = mydic.Item("ok")
        cc(1) = 44
        MsgBox (cc(1))  '这里显示cc(1)为44 也没错
        MsgBox (cc(0))  '这里显示cc(0)为1 也没错
        
        MsgBox (mydic.Item("ok")(1))  '这里还是原值2 并不是希望的
    End SubPrivate Function test() As Scripting.Dictionary
        Set test = New Scripting.Dictionary
        
        Dim a(2) As Integer
        a(0) = 1
        a(1) = 2
        a(2) = 3
        
        test.Add "ok", a
    End Function常规数组直接赋值似乎是传值的,所以你用上面的方法把字典对象的ok元素中存放的数组赋值给cc是传值,所以cc自身的变更不能引起字典对象对应元素的值的变更
      

  5.   

    test.Item("a1")(1) = 444
    这条语句其实应该拆开来看
    dim v as variant
    v = test.Item("a1") '先取得集合中 key=a1 的成员'
    v(1) = 444 '如果该返回成员是数组,给下标为1的成员赋值444'
    查看 v 这个 VARIANT 结构的内存,会发现没有 VT_BYREF 标志,说明每次 test.Item("a1") 返回数组成员时是把数组整个复制了一份返回的,所以对返回数组的修改不影响成员。如果要用 test.Item("a1")(1) = 444 修改成员数组的内容,你需要用一个 Class 封装数组 b(),并且把 Item(index) 属性设为默认。
      

  6.   

    3#和4#的代码只是少了item的关键字,一般个人习惯,为了不跟数组或者其他的视觉上混淆,所以字典对象在调用key值的时候都会写成
    dic.item("xxxx")没有指责楼上不负责任的意思,呵呵,表达让你误解的话,抱歉了, just relax!
    也难得我们两个为了个小细节探讨到7#了看来还是跟存储方法和获取方法有关,你说的class封装我不太明白,是否通过这种封装能让本来传值赋值的东西强制为传址,能给个简单的例子就拜谢了
      

  7.   

    最后一次,你可以测试下面的代码:
    Sub test()
        Dim iDic As New Dictionary, b(1) As Integer, c
        b(0) = 120
        b(1) = 300
        iDic("a1") = b
        c = iDic("a1")
        c(1) = 444
        iDic("a1") = c
        MsgBox iDic("a1")(1)''这里是444
    End Sub
      

  8.   

    'Class1
    Option ExplicitPrivate b(1) As IntegerPublic Property Get Item(ByVal Index As Long) As Integer
    Attribute Item.VB_UserMemId = 0
        Let Item = b(Index)
    End PropertyPublic Property Let Item(ByVal Index As Long, ByVal RHS As Integer)
        Let b(Index) = RHS
    End Property
    Dim test As New Scripting.Dictionary
    Dim c As New Class1
    c(0) = 100
    c(1) = 20
    test.Add "a1", c
    MsgBox (test.Item("a1")(1))test.Item("a1")(1) = 444
    MsgBox (test.Item("a1")(1))
    注:Attribute 语句是设了默认属性后自动添加的,只在 Class1.cls 文件中可见。