我试图将队列传递给VBA中的某个函数,并让该函数的操作不影响调用函数中的队列对象。
例如,在下面的代码中,队列的大小为5000.然后队列传递给RemoveOneFromQueue,大小减小到4999.我希望Main_Test中的队列不受RemoveOneFromQueue中的操作的影响。我认为在函数参数中使用ByVal会实现这一点,但它似乎没有帮助。如果可能的话,有什么想法吗?
我不想每次都重新生成队列,因为真实版本需要很长时间才能完成。
Sub Main_Test()
Dim queue As Object
Dim i As Long
Set queue = GenerateQueue()
Debug.Print queue.Count
i = RemoveOneFromQueue(queue)
Debug.Print queue.Count
End Sub
Function GenerateQueue() As Object
Dim i As Long
Dim queue As Object
Set queue = CreateObject("System.Collections.Queue")
For i = 1 To 5000
queue.Enqueue i
Next i
Set GenerateQueue = queue
End Function
Function RemoveOneFromQueue(ByVal queue As Object) As Double
Dim i As Long
i = queue.Dequeue()
RemoveOneFromQueue = i
End Function
答案 0 :(得分:0)
在VBA中,不传递对象本身。 您总是传递对实际对象的引用,因此在此场景中是否放置ByVal或ByRef无关紧要,因为两个引用都将指向同一个对象。在该引用对象上调用成员将在任何地方影响它。
但是为了修复你的特定场景,你可以实例化第二个队列并将其设置为queue.clone(),因为Queue类实现了System.ICloneable接口,所以你很幸运...试试这个:
Sub Main_Test()
Dim queue As Object
Set queue = GenerateQueue()
Debug.Print queue.Count '5000
RemoveOneFromQueue queue
Debug.Print queue.Count '5000
End Sub
Sub GenerateQueue() As Object
Dim i As Long
Dim queue As Object
Set queue = CreateObject("System.Collections.Queue")
For i = 1 To 5000
queue.Enqueue i
Next i
Set GenerateQueue = queue
End Function
Sub RemoveOneFromQueue(ByVal q As Object)
Dim q2 As Object
Set q2 = q.Clone()
q2.Dequeue
Debug.Print q2.Count '4999
End Sub
请记住,在RemoveOneFromQueue完成执行后,q2将不再存在。
但是,您是否传递引用本身ByVal或ByRef仍然很重要,如本示例所示:
Sub MainTest()
Dim queue as Object
Set queue = GenerateQueue()
Debug.Print queue.Count '5000
ChangeByVal queue
Debug.Print queue.Count '5000
ChangeByRef queue
Debug.Print queue.Count '4999
End Sub
Sub ChangeByVal(ByVal q as Object)
Dim q2 As Object
Set q2 = q.Clone()
q2.Dequeue
Debug.Print q2.Count '4999
Set q = q2
End Sub
Sub ChangeByRef(ByRef q as Object)
Dim q2 As Object
Set q2 = q.Clone()
q2.Dequeue
Debug.Print q2.Count '4999
Set q = q2
End Sub
答案 1 :(得分:0)
不幸的是,这是不可能的;(
VBA将COM Object作为参考处理。
现在你必须在你出队或复制它之后检查什么是更快的重新加入,或者使用一些本机VBA数组或者某些东西而不是Collection Object,因为它可以传递ByVal(它实际上是一个副本对象)
Function RemoveOneFromQueue(ByVal queue As Object) As Double
Dim i As Long
i = queue.Dequeue()
RemoveOneFromQueue = i
queue.Enqueue i
End Function