我有以下两个过程:
Sub OuterSub()
Dim s As String
s = "Lorem ipsum dolor sit amet"
InnerSub s
End Sub
Sub InnerSub(prm As Variant)
prm = Array(prm)
End Sub
运行OuterSub
时,在prm = Array(prm)
的{{1}}处出现以下错误:
运行时错误'13':类型不匹配
这仅在我传入类型为InnerSub
的变量时发生。以下任何一种选择均不会产生错误:
String
中将s
定义为常量:OuterSub
Const s = "Lorem ipsum dolor sit amet"
InnerSub "Lorem ipsum dolor sit amet"
中将s
定义为OuterSub
:Variant
将Dim s As Variant
定义为固定长度的字符串没有帮助。
为什么会这样?我该如何解决?
更新
在s
中声明局部String
变量也无济于事:
InnerSub
也不将参数括在括号中
Sub InnerSub(prm As Variant)
Dim s As String
s = prm
prm = Array(s)
End Sub
答案 0 :(得分:3)
此处的参数定义:
Sub InnerSub(prm As Variant)
隐式为ByRef
:
Sub InnerSub(ByRef prm As Variant)
这意味着对prm
的所有分配也将分配给s
中的OuterSub
。虽然可以将数组分配给Variant
变量prm
,但是不能将其分配给String
中的s
变量OuterSub
。
您可以通过在s As Variant
中定义OuterSub
(保存数组没有问题),并在s
完成之后检查InnerSub
的值来查看此操作
您可以显式强制变量在ByVal
中传递:
Sub InnerSub(ByVal prm As Variant)
传递常量:
Const s = "Lorem ipsum dolor sit amet"
或字符串文字:
InnerSub "Lorem ipsum dolor sit amet"
都可以,因为两者都不能在ByRef
中传递。
将参数包装在方括号中也将强制将变量传递到ByVal
中,这就是以下内容起作用的原因
Sub OuterSub()
Dim s As String
s = "Lorem ipsum dolor sit amet"
InnerSub (s) ' The brackets here do the trick
End Sub
OTOH,这两个无效的替代方法都不起作用,因为无论是创建本地字符串变量,还是将参数包装在括号中的Array
上,问题都是相同的-您正在尝试分配通过ByRef prm
参数将其转换为字符串变量的数组。
请参阅我对CallByName won't accept variant arguments的回答。从该答案中引用的链接中引用:
方法:强制值传递参数(Visual Basic)
过程声明确定传递机制。如果参数声明为ByRef,则Visual Basic希望通过引用传递相应的参数。这使过程可以更改调用代码中作为参数基础的编程元素的值。如果希望保护基础元素免遭此类更改,则可以在过程调用中通过在括号中括入参数名称来覆盖ByRef传递机制。这些括号是在调用中将参数列表括起来的括号的补充。
调用代码无法覆盖ByVal机制。
强制将参数传递给值 如果在过程中将相应的参数声明为ByVal,则无需执行任何其他步骤。 Visual Basic已经期望按值传递参数。
如果在过程中将相应的参数声明为ByRef,则在过程调用中将参数括在括号中。
答案 1 :(得分:0)
我不知道原因,但是似乎在传递byref时,期望值被抛出了。字符串是通过引用传递的,但是如果在其上加上括号,则会按值传递:
Sub OuterSub()
Dim s As String
s = "Lorem ipsum dolor sit amet"
InnerSub (s)
End Sub
如果不想更改外部函数,另一种选择是通过值定义InnerSub prm
:
Sub InnerSub(ByVal prm As Variant)
prm = Array(prm)
End Sub