我想我最近(最后)开始了解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
VB Array
在传递ByVal时引发编译器错误,可能是对此的警告
所有这些让我思考:
ByVal
和ByRef
之间有什么区别(如果有的话)Boolean
,Long
)的区别是哪些类型可以从不能ByVal
VB6
写的东西
ByVal
响应的对象?
ByVal
并返回自己的.Clone
。ByVal
,并且任何其他对象都可以模仿这种行为(同样,在Python中,所有东西都是一个对象,因此可以复制所有行为*)。或者我不必担心这种事情会发生吗?Array
的行为并在传递ByVal
时引发编译器错误 - 因为数组没有克隆方法且无法轻易复制,所以总是ByRef
* 轶事,我是Python的新手
答案 0 :(得分:3)
在我迄今为止所有的教程和参考文献中,ByRef总是&#34;传递对象&#34;,ByVal是&#34;传递对象的副本&#34;。< / p>
您是否有上述示例的链接?
对于(从类创建)的对象fragment
与Fragment
类似,而ByVal
与*foo
类似。
布尔值和长度是基元,对于基元ByRef
类似于**foo
,而ByVal
类似于bar
。
ByRef
或*bar
。ByRef
是一个32位整数,实际上是ByVal
,但只能取两个值中的一个(0 = False,-1 = True)。你不用担心,VBA会以安全的名义限制。Long
,请创建一个Type而不是一个类。对于类,您必须编写自己的浅层和深层复制构造函数。但只能使用浅层和深层Boolean
来复制类型。
数组和类型传递ByRef
,因为它们是在堆栈上创建的。
答案 1 :(得分:1)
对于VBA中的对象和类,传递byval或byref没有实际区别。传递byref ony意味着指针被传递&#39; byref&#39;,对象保持不变。
如果你想到它,它对(Excel)对象有意义;你是否通过 范围(&#34; A1&#34;)byref或byval,它仍然是我们正在寻址的同一个单元格。