Com 是否将右值作为ByRef参数传递给VB6?

Com 是否将右值作为ByRef参数传递给VB6?,com,vb6,parameter-passing,Com,Vb6,Parameter Passing,背景:我有一套VB6 DLL,它们共享一个共同的“接口”。无论本地安装哪个版本,都会通过COM互操作调用此接口的成员(从VB.Net代码,我怀疑这可能很重要)。我今天注意到,其中一个调用将[我理解为]一个右值(以下简称“右值”)传递给一个VB6函数,该函数没有定义为ByVal的特定参数 示例代码: VB6: VB.Net: ' get an instance of the VB6 class and pass our trimmed localString to it result = vb6I

背景:我有一套VB6 DLL,它们共享一个共同的“接口”。无论本地安装哪个版本,都会通过COM互操作调用此接口的成员(从VB.Net代码,我怀疑这可能很重要)。我今天注意到,其中一个调用将[我理解为]一个右值(以下简称“右值”)传递给一个VB6函数,该函数没有定义为
ByVal
的特定参数

示例代码:

VB6:

VB.Net:

' get an instance of the VB6 class and pass our trimmed localString to it
result = vb6Instance.VB6Function(localString.Trim())
' Do interesting things with localString
我还没有注意到VB6代码改变
input
值的实例,但我也没有对不同的DLL实现进行彻底的搜索(有几百个)

如果
VB6Function
input
为“右值”时更改了
input
的值,会发生什么情况?就这点而言,为什么在传递“一个右值”时,这个方法调用不会出错呢

如果VB6函数在输入为“右值”时更改了输入的值,会发生什么情况

没什么。或者说,没什么有趣的

当被调用函数更改其参数的值时,无论参数是由val还是byref提供,该函数的内部都没有区别。重要的是存在某种类型的变量,因此可以对其进行操作

就这点而言,为什么在传递“一个右值”时,这个方法调用不会出错呢

为什么会出错?将参数作为正确的类型(字符串)传递,这才是最重要的

VB中没有右值的概念。
当您将要调用的右值传递给通过引用接受某个内容的方法时,编译器会自动将引用传递给右值实际驻留的方法。方法获取其值byref,调用方不关心指针

localString.Trim()
分配并返回字符串。它有一个地址,可以传阅。代码没有显式捕获该地址,但编译器将其传递给
VB6Function
byref没有问题。如果
VB6Function
更改了该值,它将更改临时位置所指向的内容,这没有明显的差异,因为无论哪种方式调用后,它都将被销毁

至于为什么有些人可能更喜欢在VBA中接收字符串byref,特别是为了避免每次调用函数时复制整个字符串。在VB.NET中这不是问题,因为那里的字符串是不可变的,因此可以通过byval传递,而无需复制,但在VBA中情况并非如此,因此需要克隆byval字符串以用于调用。人们通过指定byref来避免这种情况,尽管从技术上讲,这让他们能够处理传递的变量

如果VB6函数在输入为“右值”时更改了输入的值,会发生什么情况

没什么。或者说,没什么有趣的

当被调用函数更改其参数的值时,无论参数是由val还是byref提供,该函数的内部都没有区别。重要的是存在某种类型的变量,因此可以对其进行操作

就这点而言,为什么在传递“一个右值”时,这个方法调用不会出错呢

为什么会出错?将参数作为正确的类型(字符串)传递,这才是最重要的

VB中没有右值的概念。
当您将要调用的右值传递给通过引用接受某个内容的方法时,编译器会自动将引用传递给右值实际驻留的方法。方法获取其值byref,调用方不关心指针

localString.Trim()
分配并返回字符串。它有一个地址,可以传阅。代码没有显式捕获该地址,但编译器将其传递给
VB6Function
byref没有问题。如果
VB6Function
更改了该值,它将更改临时位置所指向的内容,这没有明显的差异,因为无论哪种方式调用后,它都将被销毁


至于为什么有些人可能更喜欢在VBA中接收字符串byref,特别是为了避免每次调用函数时复制整个字符串。在VB.NET中这不是问题,因为那里的字符串是不可变的,因此可以通过byval传递,而无需复制,但在VBA中情况并非如此,因此需要克隆byval字符串以用于调用。人们通过指定byref来避免这种情况,尽管从技术上讲,这让他们能够处理传递的变量。

这种行为与中的行为之间有一个有趣的相似之处:“因为您使用的是括号,所以值是通过值强制传递的,而不是通过引用(编译器创建一个临时副本并通过引用传递)。“我认识到在VB6和VB.Net之间的特定调用约定(使用参数调用SUB)发生了变化,但类似的调用非常有指导意义,因为它演示了相同的行为,即使调用机制(VB6->VB6 vs VB.Net->VB6)也不例外不同。@arootbeer在链接答案中使用parens是99%的错误,对于那些编码风格不好的情况,只剩下1%的错误。如果需要临时副本,可以使用类似
CLng(longVar)
CStr(stringVar)
的方法来明确想法。@wqw如果我看到
CLng(longVar)
,其中
longVar
实际上是
Long
,它肯定不会让我明白这个想法。相反,我会认为它是
longVar
不是
Long
时代遗留下来的代码,我会删除
CLng
,另一方面,让意图明确无误。@GSerg如果我看到的话关于单参数函数的附加括号我肯定不会对这段代码的原始作者给予太高的评价,我可能会尝试
' get an instance of the VB6 class and pass our trimmed localString to it
result = vb6Instance.VB6Function(localString.Trim())
' Do interesting things with localString