为什么带有参数的类的方法需要“ Call”关键字?

时间:2019-01-25 15:34:10

标签: excel vba

我的课有多种方法。一些方法采用参数。这些方法需要关键字“ Call”才能起作用。为什么?

MyObject.MyMethod   'Works just fine without Call.

Call MyObject.MyMethod(arg1, arg2)  'Requires Call. Won't compile without it.

2 个答案:

答案 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