我想我最近(终于)开始了解 ByVal
和 ByRef
在 VBA 中的工作方式。
观察
在我迄今为止所经历的所有教程和引用文献中,ByRef
总是“传递对象”,ByVal
总是“传递对象的副本”。对我来说,后者意味着对象在内存中的位置被复制,并返回一个指向该新位置的指针。我现在意识到情况并非总是如此,事实上据我所知,这种情况很少发生:相反,大多数对象和类实际上都传递了 ByRef
,即使在例程的签名中指定了 ByVal
。System.Collections.ArrayList
以 ByRef 静默方式传递,如以下代码所示:
Sub test()
Dim list1 As Object, list2 As Object
Set list1 = CreateObject("System.Collections.ArrayList")
list1.Add "foo"
Set list2 = RemoveItem(list1)
Debug.Assert list2.Contains("foo") = False 'as expected
Debug.Assert list1.Contains("foo") = True 'raises error, meaning list1 was passed byref not byval
End Sub
Function RemoveItem(ByVal list As Object) As Object 'ByVal
list.Remove "foo" 'expect to remove from a copy and return that
Set RemoveItem = list
End Function
考虑到我对
ByVal
的了解,这让我感到惊讶。进一步挖掘告诉我,要从 ByVal
获得我想要的副本,我需要传递的对象具有启用此功能的方法。对于 ArrayList
, .Clone
方法进行浅拷贝。所以我的功能变成:Function RemoveItem(ByRef list As Object) As Object 'ByRef or ByVal, makes no difference
Dim listCopy As Object
Set listCopy = list.Clone 'make a shallow copy of the object
listCopy.Remove "foo" 'actually remove from a copy and return that
Set RemoveItem = listCopy
End Function
当传递 ByVal 时,VB
Array
会引发编译器错误,这可能是针对此的警告问题
这一切让我想到:
ByVal
和 ByRef
之间有什么区别(如果有)Boolean
、 Long
),这些类型可以从不能 ByVal
VB6
编写的东西ByVal
响应的对象?ByVal
并返回自身的 .Clone
。 ByVal
以及任何其他对象是否可以模仿这种行为(同样,在 Python 中,一切都是对象,因此一切行为都可以复制*)。或者我不必担心这种情况会发生吗? Array
的行为并在传递 ByVal
时引发编译器错误 - 因为数组没有克隆方法并且不能容易地复制所以总是 ByRef
*轶事,我对 Python 很陌生
最佳答案
你有上面例子的链接吗?
ByVal
就像 *foo
而 ByRef
就像 **foo
。 ByVal
就像 bar
而 ByRef
就像 *bar
。 ByRef
或 ByVal
。 Long
是一个 32 位整数,Boolean
实际上也是,但只能取两个值之一(0=False,-1=True)。您不用担心,VBA 以安全的名义进行了限制。 ByRef
给你的对象,那么创建一个 Type 而不是一个类。 =
无论是浅的还是深的来复制。 数组和类型被传递
ByRef
因为它们是在堆栈上创建的。关于excel - ByVal 是谎言吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49845406/