VBScript中的ByRef和ByVal

Jér*_*ôme 31 vbscript

我在VBScript中遇到了一些奇怪的事情.在编写我希望通过引用传递参数的过程时,调用此过程的方式会改变参数的传递方式!

这是一个例子:

Sub IncrementByRef(ByRef Value)
   Value = Value + 1
End Sub

Sub IncrementByVal(ByVal Value)
   Value = Value + 1
End Sub

Dim Num
Num = 10
WScript.Echo "Num : " & Num
IncrementByRef(Num) : WScript.Echo "IncrementByRef(Num) : " & Num
IncrementByRef Num  : WScript.Echo "IncrementByRef Num : " & Num
IncrementByVal(Num) : WScript.Echo "IncrementByVal(Num) : " & Num
IncrementByVal Num  : WScript.Echo "IncrementByVal Num : " & Num
Run Code Online (Sandbox Code Playgroud)

这是输出:

U:\>cscript //nologo byrefbyval.vbs
Num : 10
IncrementByRef(Num) : 10
IncrementByRef Num : 11
IncrementByVal(Num) : 11
IncrementByVal Num : 11

U:\>
Run Code Online (Sandbox Code Playgroud)

当指定参数传递ByVal时,无论调用过程的方式如何,它都按预期工作.但是当指定参数传递ByRef时,如果以这种方式调用过程,它将按预期工作:

IncrementByRef Num
Run Code Online (Sandbox Code Playgroud)

但不是这样的:

IncrementByRef(Num)
Run Code Online (Sandbox Code Playgroud)

这对我来说似乎很奇怪.有没有办法确保参数是通过ByRef传递的,无论程序是如何调用的?

Hel*_*len 40

Eric Lippert有一篇关于在VBScript中使用括号的好文章: 你的意思是"不能使用括号?" 你的例子说明了他提到的一个要点,即:ByRef用括号括起一个参数将其传递给ByVal.

简而言之,VBScript子例程调用中的括号不仅可以放在参数列表周围,还可以放在各个参数周围(在这种情况下它们是强制的ByVal).并且VBScript只希望如果使用Call关键字,则将参数列表括在括号中.由于IncrementByRef(Num)调用不使用Call关键字,因此VBScript将括号视为应用于子例程参数,因此将其传递ByVal而不是ByRef.

令人困惑,但这就是它的工作方式.

  • @mnemotronic,它也可以在 Eric 的博客中找到:https://ericlippert.com/2003/09/15/what-do-you-mean-cannot-use-parentheses/。我已经更新了答案中的链接。 (2认同)

Joe*_*orn 19

这是一个功能,而不是一个错误:http:
//msdn.microsoft.com/en-us/library/ee478101.aspx

如果参数括在括号中且括号不适用于参数列表,则ByRef参数按值传递.

如果满足下列条件之一,则括号将应用于参数列表:

  • 该语句是一个函数调用,具有对返回值的赋值.

  • 该语句使用Call关键字.(Call关键字可以选择用于子程序调用,或者用于没有赋值的函数调用.)

因此,请尝试使用Call关键字或让它返回一个值.

  • 这是我见过的与VBScript相关的最令人困惑的MSDN主题之一 (7认同)

Ant*_*nes 7

要清楚.括号有三个不同的目的.

  1. 用于在定义或调用过程时包含参数列表
  2. 指示数组上的索引器.
  3. 作为表达式中的运算符.

有两种方法可以将过程作为语句或表达式来调用.

表达:-

x = func(y)
Run Code Online (Sandbox Code Playgroud)

声明:-

func y
Run Code Online (Sandbox Code Playgroud)

请注意,Call关键字调用过程就好像它是表达式的一部分,因此参数列表必须包含在parantheses中.

在上面,这y本身代表了一个非常简单的尝试.我们现在可以使用y + z了.实际上我们可以使用任何有效的表达式,包括使用括号运算符的表达式.例如:-

 x = (y)
Run Code Online (Sandbox Code Playgroud)

是一个有效的表达.因此,当你这样做: -

 func(y)
Run Code Online (Sandbox Code Playgroud)

VBScript看到对func表达式结果(y)传递的调用.现在,即使func将此参数定义为ByRef值,y也不会受到影响,因为y实际上并未将其作为参数传递.传递的是表达式的结果(y),它将存储在某个临时的地方.即使这个临时存储被修改func它也会在之后被丢弃,因此在标记参数时具有相同的行为ByVal.