gpt4 book ai didi

excel - ByVal 是谎言吗?

转载 作者:行者123 更新时间:2023-12-02 16:34:55 24 4
gpt4 key购买 nike

我想我最近(终于)开始掌握 ByValByRef 在 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 时会引发编译器错误,也许只是针对此问题的警告

问题

所有这些让我思考:

  1. 对于类/对象,ByValByRef 之间有什么区别(如果有)
  2. 可以通过 ByVal 传递的某些类型(BooleanLong)与不能通过 ByVal 传递的类和类型有何区别
  3. 就库引用而言 - 可能无法用 VB6 编写的内容
    • 是否可以创建具有默认 ByVal 响应的对象?
      • 在 Python 中,您可以指定类对不同关键字的 react 方式。我怀疑您是否可以在 VBA 中本地执行此操作,但是用更通用的语言编写的对象是否可以说,检测它是否被传递 ByVal 并返回 .Clone本身。
      • 换句话说,VBA 的内置数据类型如何传递 ByVal 以及任何其他对象是否可以模仿此行为(同样,在 Python 中,一切都是对象,因此一切行为都可以复制*)。或者我不必担心这种情况发生?
    • 是否可以模仿Array的行为并在传递ByVal时引发编译器错误 - 因为数组没有克隆方法并且无法轻松复制,所以始终ByRef
  4. 是否有 Sub、Function 或方法可以让我创建对象的深拷贝?也就是说,复制一个对象使用的内存并创建对象的第二个副本的通用方法。

*轶事,我对 Python 很陌生

最佳答案

In all the tutorials and references I've been through to date, ByRef was always "passing the object", ByVal was "passing a copy of the object".

您有上述示例的链接吗?

  1. 对于对象(从类创建)ByVal就像 *foo同时ByRef就像 **foo

  2. Boolean 和 Long 是基元,对于基元 ByVal就像 bar同时ByRef就像 *bar .

    • 没有
      • 对象无法判断它是否已通过 ByRefByVal .
      • VBA“内置”数据类型在 C/C++ 中具有类似物,因此 Long是一个 32 位整数,所以 Boolean事实上,但只能取两个值之一(0=False,-1=True)。您不必担心,VBA 以安全的名义进行了限制。
    • 如果您想强制通过 ByRef然后为您的对象创建一个类型而不是类。
  3. 对于类,您必须编写自己的浅拷贝构造函数和深层拷贝构造函数。但是类型可以通过使用 = 来复制既浅又深。

数组和类型通过 ByRef因为它们是在堆栈上创建的。

关于excel - ByVal 是谎言吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49845406/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com