VB6传递值并通过引用传递

w00*_*977 12 vb6 vbscript vba

我正在努力理解按值传递并在VB6中通过引用传递.我完全理解这些概念是面向对象的编程语言,如.NET和Java(我意识到Java没有通过引用传递).看看下面的代码:

Private Sub Form_Load()

Dim Test As Integer
Test = 1
TestFunction Test 'line 5
MsgBox (Test)

End Sub

Private Sub TestFunction(ByVal i As Integer)
    i = i + 1
End Sub
Run Code Online (Sandbox Code Playgroud)

当我在第5行的Test周围放置括号时,消息框会按照我的预期打印1.现在看看下面的代码:

Private Sub Form_Load()

Dim Test As Integer
Test = 1
TestFunction Test 'line 5
MsgBox Test

End Sub

Private Sub TestFunction(ByRef i As Integer)
    i = i + 1
End Sub
Run Code Online (Sandbox Code Playgroud)

消息框按照我的预期打印2.但是,如果在第5行添加括号,则消息框将打印1,这是我不希望的.即使被调用函数中定义的变量是ByRef,看起来调用函数也可以通过值传递.反之亦然,即如果被调用函数具有定义为ByVal的变量的签名,则它将始终为ByVal(即使调用函数中的变量周围没有括号).在VB6中,这背后的想法是什么?我意识到这是VB6中的一个基本问题,但它让我很困惑.我已经阅读了MSDN文档,我意识到这一切都是正确的,但它并没有解释它背后的原因.

Mar*_*rkJ 19

这是VB6中的经典问题.它在VB6手册中解释.在下面的代码中,VB6将参数视为表达式(Test)而不是变量引用

TestFunction (Test)
Run Code Online (Sandbox Code Playgroud)

为了传递对变量的引用,要么省略括号,要么使用遗留Call语句(需要括号)

TestFunction Test
Call TestFunction(Test)
Run Code Online (Sandbox Code Playgroud)

VB6允许您将表达式传递给ByRef参数,即使方法更改它们也是如此.你可以写

TestFunction (Test + 2)
Run Code Online (Sandbox Code Playgroud)

编译器创建一个临时副本并通过引用传递它.VB.Net 以类似的方式使用括号.

如果TestFunction采用如下两个参数,您也可以让编译器创建临时副本:

TestFunction (one), (two)
Run Code Online (Sandbox Code Playgroud)

即使Call您将括号加倍,也可以添加一个额外的不必要的副本,您可以获得临时副本:

Call TestFunction((Test))
Run Code Online (Sandbox Code Playgroud)

  • 我不确定这是一个"陷阱",因为它是有记录的,故意的行为.Call关键字是遗留的并且已弃用,可以追溯到早期的MS Basics.正是为了方便移植旧程序. (2认同)
  • 无论参数是否被视为表达式,`Call`关键字都没有.它只是使用括号作为传递参数的方式,因此一对括号具有不同的含义.但是参数周围的括号会产生一个表达式,就像没有`Call`关键字一样. (2认同)
  • @Bob我称之为骗局,因为它是众所周知的语言陷阱,难以理解并容易陷入新手.这是我对陷阱的理解.Mirriam-韦伯斯特字典:*陷阱*意外的令人不安的挑战,启示或捕获.意图和文件(我已经链接)在这种情况下是不够的,以阻止它成为一个陷阱. (2认同)
  • @Bob不,我不相信我的话可以证明任何事情都是不可取的.只有经常被误解的东西才会被误解.我希望我提供一些友好的批评语言,而不是消极(我喜欢VB!).虽然我试图通过告诉他们他们并不是唯一一个发现这种困难的人来鼓励学习者.这在教学中很重要. (2认同)

Jon*_*ood 6

将括号内的任何表达式括起来会导致在执行任何其他操作之前首先计算该表达式,即使该表达式只是单个变量也是如此.在您的情况下,该表达式的结果然后作为参数传递.

所以,你实际上是通过引用传递参数.但是你传递的参数是表达式的结果,而不是原始变量.这就是原始变量未更新的原因.