忘了之前有沒有碰到過這樣的問題
先描述下問題,使用字典物件中再存放陣列目的是為了
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
uj5u.com熱心網友回復:
b(1)=444test("a1")=b
msgbox test("a1")(1)
uj5u.com熱心網友回復:
樓上的方法可以解決直接賦值導致無效的問題不過并不藝術,因為
實際應用中我會把這個字典物件以傳址的方式傳遞給別的函式或者方法,此時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")(...)這個寫法的問題。
uj5u.com熱心網友回復:
你試試這樣:''.....
dim c
c=test("a1")
c(1)=444
test("a1")=c
msgbox test("a1")(1)
'''......
uj5u.com熱心網友回復:
謝謝樓上的回復 不過親 很抱歉 只能說你的代碼沒測驗過
顯示值依然是賦值之前的原值
下面把測驗代碼發出來
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 Sub
Private 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自身的變更不能引起字典物件對應元素的值的變更
uj5u.com熱心網友回復:
你好好看看#3代碼和你#4樓代碼,,,,看仔細了.........一行一行的比較uj5u.com熱心網友回復:
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) 屬性設為默認。
uj5u.com熱心網友回復:
3#和4#的代碼只是少了item的關鍵字,一般個人習慣,為了不跟陣列或者其他的視覺上混淆,所以字典物件在呼叫key值的時候都會寫成dic.item("xxxx")
沒有指責樓上不負責任的意思,呵呵,表達讓你誤解的話,抱歉了, just relax!
也難得我們兩個為了個小細節探討到7#了
看來還是跟存盤方法和獲取方法有關,你說的class封裝我不太明白,是否通過這種封裝能讓本來傳值賦值的東西強制為傳址,能給個簡單的例子就拜謝了
uj5u.com熱心網友回復:
最后一次,你可以測驗下面的代碼: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
uj5u.com熱心網友回復:
呃 確實疏忽了,原諒我的粗心,陣列改完之后沒有回給字典物件試了下是可行的,比第一種相對簡單
uj5u.com熱心網友回復:
'Class1
Option Explicit
Private b(1) As Integer
Public Property Get Item(ByVal Index As Long) As Integer
Attribute Item.VB_UserMemId = 0
Let Item = b(Index)
End Property
Public 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 檔案中可見。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/105148.html
標籤:VB基礎類
上一篇:請問下,vb+mysql 如何使用排名,然后調取所有排名資料??
下一篇:求助 如何記憶表單資料
