我的课有多种方法。一些方法采用参数。这些方法需要关键字“ Call”才能起作用。为什么?
MyObject.MyMethod 'Works just fine without Call.
Call MyObject.MyMethod(arg1, arg2) 'Requires Call. Won't compile without it.
答案 0 :(得分:4)
Call
。实际上,自从隐式调用语法在Visual Basic 4.0中问世以来,如果我没记错的话,它已经过时了。
object.MemberName arg1, arg2
请注意括号已消失。如您所述,这将是非法的:
object.MemberName (arg1, arg2)
请注意MemberName
和开头(
之间的空格:VBE总是在其中放置一个空格。这就是VBE说的“好吧,所以我将这些括号中的内容用作表达式,并将其作为结果通过表达式按值传递(无论成员的签名明确指定了ByRef
还是而不是您要调用的成员”。除了(foo, bar)
不是合法表达式之外,因此代码不会编译。
当MemberName
返回调用者需要捕获的值时,括号的行为会有所不同:
foo = object.MemberName(arg1, arg2)
请注意,不再有空格;如果添加任何VBE,它将删除它。
因此,举一个更熟悉和具体的示例-请注意,它与对象和成员无关:
MsgBox "Yes?", vbYesNo ' works fine
Call MsgBox("Yes?", vbYesNo) ' works fine
Call VBA.Interaction.MsgBox("Yes?", vbYesNo) ' works fine
MsgBox ("Yes?", vbYesNo) ' illegal
result = VBA.Interaction.MsgBox("Yes?", vbYesNo) ' works fine
Call
关键字仅在VBA6 / VBA7中出于向后兼容的目的而存在,就像许多许多其他语言构造一样(想到While...Wend
)。这就是Rubberduck(免责声明:我是该开源项目的管理员之一)将其使用标记为“过时”并提供删除它的工具的原因。
答案 1 :(得分:3)
@MathieuGuindon的答案涵盖了真正出色的部分,因此我认为我将解决“为什么”部分。
VB的语法将括号作为语法元素重载。对于过程调用,它们用于包围argument list:
argument-list = [positional-or-named-argument-list] positional-or-named-argument-list = *(positional-argument ",") required-positional-argument positional-or-named-argument-list =/ *(positional-argument ",") named-argument-list named-argument-list = named-argument *("," named-argument)
请注意,参数列表(5.6.13.1)的定义属于索引表达式(5.6.13)的类别,这并不简单用词不当,因为解析器必须静态确定正在索引的内容。 ()
也用于数组索引和索引成员索引这一事实使情况变得复杂。
Call
语句本身(5.4.2.1)消耗了一个参数列表,但是括号也可以用作变量(数组等)的索引器这一事实意味着存在如果没有以下规则,则Call
右边的表达式可能是不明确的:
- 如果指定了 Call 关键字:
- 如果
元素的引用表达式是 ,则指定的参数列表就是该表达式的参数列表。 - 否则,指定的参数列表是一个空的参数列表。
强制使用括号消除了这种歧义。一个例子就是这样:
Sub Foo()
Dim Bar As Object
Call Bar 1 '<-- What is Bar here? Is this the default member of the object, or the Sub?
Bar 1 '<-- This in unambiguous, because ( ) are required to use a default member indexer.
End Sub
Sub Bar(paramater As Integer)
'Do something
End Sub