在VBA中传递队列对象byval-调用函数对象';不能在被调用函数中更改
我试图将队列传递给VBA中的函数,并使该函数的操作不影响调用函数中的队列对象 例如,在下面的代码中,队列以5000大小开始。然后队列被传递到RemoveOneFromQueue,其大小减小到4999。我希望Main_测试中的队列不受RemoveOneFromQueue中操作的影响。我认为在函数参数中使用ByVal可以实现这一点,但似乎没有帮助。如果可能的话,有什么想法吗 我不想每次都重新生成队列,因为真正的版本需要很长时间才能完成在VBA中传递队列对象byval-调用函数对象';不能在被调用函数中更改,vba,excel,Vba,Excel,我试图将队列传递给VBA中的函数,并使该函数的操作不影响调用函数中的队列对象 例如,在下面的代码中,队列以5000大小开始。然后队列被传递到RemoveOneFromQueue,其大小减小到4999。我希望Main_测试中的队列不受RemoveOneFromQueue中操作的影响。我认为在函数参数中使用ByVal可以实现这一点,但似乎没有帮助。如果可能的话,有什么想法吗 我不想每次都重新生成队列,因为真正的版本需要很长时间才能完成 Sub Main_Test() Dim queue As
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
在VBA中,对象本身不会被传递。 您总是传递对实际对象的引用,因此在此场景中放置ByVal还是ByRef并不重要,因为两个引用都指向同一个对象。调用引用对象上的成员将影响该对象的所有位置 但是,为了修复您的特定场景,您可以实例化第二个队列并将其设置为queue.clone(),因为queue类实现了System.IClonable接口,所以您很幸运。。。试试这个:
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将不再存在
但是,不管您是通过val还是通过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
在VBA中,对象本身不会被传递。 您总是传递对实际对象的引用,因此在此场景中放置ByVal还是ByRef并不重要,因为两个引用都指向同一个对象。调用引用对象上的成员将影响该对象的所有位置 但是,为了修复您的特定场景,您可以实例化第二个队列并将其设置为queue.clone(),因为queue类实现了System.IClonable接口,所以您很幸运。。。试试这个:
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将不再存在
但是,不管您是通过val还是通过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
不幸的是,这是不可能的;( VBA将COM对象作为引用处理 现在,您必须检查出队列后重新排队更快的方法,或者创建一个副本,或者使用一些本机VBA数组或其他方法代替集合对象,因为它可以通过val传递(实际上是对象的副本)
不幸的是,这是不可能的( VBA将COM对象作为引用处理 现在,您必须检查出队列后重新排队更快的方法,或者创建一个副本,或者使用一些本机VBA数组或其他方法代替集合对象,因为它可以通过val传递(实际上是对象的副本)
如果您不想从队列中删除该项,那么为什么要使用队列?或者使用Peek而不是Dequeue,但现在还不清楚您真正想在这里做什么…我首先要重命名您的变量,因为队列是类的名称,因此不能用作变量。这是因为您传递了对
集
对象的引用其中一个类似于C/C++指针。你可以传递一个新指针,但它仍然指向同一个内存块。这与传递一个指定的长、字符串甚至变量不同,因为这些都是独立的分配内存块。你可以只生成两个队列,然后将一个队列传递给RemoveOneeFromQueue
函数。但我不确定这是否是您想要的,但您到底想要什么也不清楚。如果您不想从队列中删除该项目,那么为什么要使用队列?或者使用Peek而不是Dequeue,但不清楚您在这里真正想要做什么…我首先要重命名您的变量,因为队列是类因此不能用作变量。这是因为您传递了对集
对象的引用。我认为这些类似于C/C++指针。您可以传递一个新指针,但它仍然指向同一内存块。这与传递指定的长、字符串甚至变量不同,因为它们是独立的l和独立分配的内存块。您可以只生成两个队列,然后将一个队列传递给removeonefromqueue
函数。但我不确定这是您想要的,但您到底想要什么也不清楚。太好了!使用clone()更好,不会出现速度损失。太好了!使用clone()更好显示没有速度损失。