我有以下两个程序:
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
Run Code Online (Sandbox Code Playgroud)
当我运行时OuterSub,我在prm = Array(prm)in处收到以下错误InnerSub:
运行时错误“13”:类型不匹配
只有当我传入一个类型为 的变量时才会发生这种情况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
Run Code Online (Sandbox Code Playgroud)
也不将参数包装在括号中:
Sub InnerSub(prm As Variant)
prm = Array((prm))
End Sub
Run Code Online (Sandbox Code Playgroud)
这里的参数定义:
Sub InnerSub(prm As Variant)
Run Code Online (Sandbox Code Playgroud)
是隐含的ByRef:
Sub InnerSub(ByRef prm As Variant)
Run Code Online (Sandbox Code Playgroud)
这意味着任何分配 toprm也将分配给sin OuterSub。虽然阵列可分配给该Variant变量prm,它不能被分配给该String变量s在OuterSub。
您可以通过定义s As Variantin OuterSub(保存数组没有问题)并检查safterInnerSub已完成的值来查看此操作。
您可以明确强制传入一个变量ByVal:
Sub InnerSub(ByVal prm As Variant)
Run Code Online (Sandbox Code Playgroud)
传递一个常量:
Const s = "Lorem ipsum dolor sit amet"
Run Code Online (Sandbox Code Playgroud)
或字符串文字:
InnerSub "Lorem ipsum dolor sit amet"
Run Code Online (Sandbox Code Playgroud)
两者都有效,因为两者都不能传入ByRef。
将参数包装在方括号中也会强制传入变量ByVal,这就是以下工作的原因
Sub OuterSub()
Dim s As String
s = "Lorem ipsum dolor sit amet"
InnerSub (s) ' The brackets here do the trick
End Sub
Run Code Online (Sandbox Code Playgroud)
OTOH,您的非工作替代方案都不起作用,因为无论您是创建本地字符串变量,还是将参数包装Array在括号中,问题都是一样的——您试图通过ByRef prm范围。
请参阅我对CallByName 的回答不会接受变体参数。引用该答案中引用的链接:
如何:强制按值传递参数 (Visual Basic)
过程声明决定了传递机制。如果参数声明为 ByRef,则 Visual Basic 期望通过引用传递相应的参数。这允许该过程更改调用代码中作为参数基础的编程元素的值。如果您希望保护底层元素免受此类更改,您可以通过将参数名称括在括号中来覆盖过程调用中的 ByRef 传递机制。这些括号是对调用中包含参数列表的括号的补充。
调用代码不能覆盖 ByVal 机制。
强制参数按值传递 如果相应的参数在过程中声明为 ByVal,则不需要采取任何额外的步骤。Visual Basic 已经期望按值传递参数。
如果相应的参数在过程中声明为 ByRef,则在过程调用中将参数括在括号中。