通话关键字-是否已弃用

FAB*_*FAB 8 vba

在此处输入图片说明

一段时间以来,我已经看到有人提到“ 呼叫声明”已被弃用,但是我似乎找不到任何官方证据来支持这一说法。

文档页面上页面上有一个相当近期的更新(12/03/2018),所以不能说是过时的信息。

大部分时间,我一直在代码中使用Call,原因仅在于:

Call function(arg1, arg2, arg3) 比...更具可读性 function arg1, arg2, arg3

现在,对于这个问题,谁能提供一些我为什么不应该再使用该Call语句的见解?如果您确实不赞成使用,请提供指向资源的链接。

如果这个问题违反了网站规则,请告诉我,我会很乐意将其删除,尽管很高兴得到答复。

Mat*_*don 15

一致性为王

无论您呼叫a Sub还是a Function都没有任何区别。重要的是一致性就是Call-lovers声称使用关键字带来的含义。与是否在参数列表周围加括号保持一致。

因此,代替此简单易用的隐式调用语句:

MsgBox "I'm a function but you're discarding my return value, so no parentheses."
Run Code Online (Sandbox Code Playgroud)

我们得到这样的事情:

MsgBox ("I'm a function but you're discarding my return value, and this call looks weird.")
Run Code Online (Sandbox Code Playgroud)

而且我还没有看到Call 实际使用的任何实际一致性

Call MsgBox("I'm a function but you're discarding my return value, so I have a Call keyword.")
Call MyProcedure(42)
Call ActiveSheet.Range("A1:A10").Clear
Call Beep
Call CallByName(obj, "SomeMethod", VbCalType.VbMethod)
Run Code Online (Sandbox Code Playgroud)

持续使用会Call很快变得令人讨厌,明显多余并减慢阅读速度,因为眼睛不由自主地停下了关键字,然后大脑开始“哦,小心,我们在这里称呼某些东西”。我想您有时会停止看到它,只是感觉好像丢失了某些东西。

每个单个可执行语句中的绝大多数将是在某种抽象级别上对某处某处的调用– Call一致地使用使该语言比现在已经笨重得多。

除非Call不是真正的一致性,否则更多的是能够轻松地查看我自己的用户过程调用 ……在这一点上,这只是抓住稻草来使一个毫无用处的古老构造合法化:没有合法的用途。Call关键字

这是唯一的“合法”用例:

Public Sub Test()
DoSomething: DoSomethingElse
'vs.
'Call DoSomething: Call DoSomethingElse
End Sub

Private Sub DoSomething() '<~ dead code. can you see why?
End Sub

Private Sub DoSomethingElse()
End Sub
Run Code Online (Sandbox Code Playgroud)

所述Call关键字歧义消除一个LineLabel:从一个ParameterlessProcedureCall接着一个:指令隔板。唯一的问题是,:指令分隔符非常适合在单一代码行上打入和塞满尽可能多的可执行代码……它们对于可读性而言很糟糕。此外,每个人都同意a NEWLINE应该;以任何以分号结尾的语言跟随a ,即使对于编译器而言,忽略行跳转是非常有意义的

我们编写代码供人们阅读和维护,而不仅仅是供编译器构建和运行。


不赞成使用?谁说的?

我和我的小鸭

我100%确信我一生中曾经读过“官方”文档,但该关键字已过时。哎呀,它甚至被指定为多余的。语言不断发展,VBA也不例外-即使具有令人难以置信的令人难以置信的水平向后兼容性,并且经过二十年没有任何形式的重大改变,语言-或更确切地说,即使维护者已宣誓退役语言仍然是不固定的随它去吧

Call它不是VBA中唯一被弃用的令牌,但出于可疑的主观原因,与人们用来证明坚持本世纪系统匈牙利符号在本世纪所犯的巨大错误并不相同,其根源很深。

Rem评论标记的捍卫者在哪里?为什么While...Wend仍然是事物Do While...Loop?有人在Error陈述中提出错误而不是通过错误Err.Raise吗?使用Error$而不是通过输出错误消息Err.Description?用清晰易懂的$&%^!#类型提示声明变量类型?谁写的On Local Error?为什么要使用Global真正的东西Public

而且,如果显式Call不是过时的并且“使代码更具可读性”,那么为什么Let出于相同的显式/明确性原因,同一个人为什么不使用显式语句进行值分配?

我认为现在已经是重写最佳实践的最佳时机了,Call过去,该过程与Let匈牙利符号和程序顶部的声明墙一起过去。每个编程社区都已经做到了这一点-只有VBA社区仍在坚持30年前的“最佳实践”,以获取全新的代码,而不仅仅是另一个时代编写的遗留代码。我怀疑,即使不考虑基本的IDE ,VBA的“恐惧分数”也很有可能与此有关。

我很希望能够从Microsoft MVP老朋友Rob Bovey和Stephen Bullen那里得到一个参考,然后说:“在这里,请参阅第172页,它说call关键字已经过时了 ”(这个答案似乎提到了“两个VBA上的一英寸厚的书基本上说不要使用它,除非您想使用VBE的“查找”功能轻松地在大型项目中查找呼叫”),所以可能就是这样,但是在任何情况下,这些专家本质上都已定义最佳实践是什么,“重构”是一个外来词,“单元测试”是一个极端的编程疯狂想法-整个编程环境在过去20年中发生了巨大的变化,但VBA却停滞不前。是时候结束这个了,继续前进。

谈到前进 ...

“它使迁移到VB.NET更容易”

据称,使用Call语句使将代码移植到.NET变得“更加容易”,因为VB.NET将在任何地方都需要括号。恭喜,那是布洛克。首先,因为您要移植VBA代码的不是VB.NET,而是TypeScript(如果确实要进行任何形式的移植),则很有可能。如果您手动复制VBA代码并对其进行“翻译”以使其可以在目标语言中进行编译,则会很快发现不必处理括号是非常有限的事情,因为实际上其他所有内容都需要重写, ......包括下降Call令牌。

写小,专业的程序,如果以往任何时候都多单一个做很少的事情,利用抽象层次和类/对象,异径接头之间的模块,提高凝聚力的模块,让您的代码的行为覆盖和全面的单元测试记录,将帮助您更快地移植VBA代码,并确保移植的代码工作相同。Call括号只是保持坏习惯的借口。


Vit*_*ata 5

Call由于以下原因,我尝试避免使用该变量(因此对我来说是贬值的)-在#VBA中,我考虑将括号中的变量作为超载参数标准ByVal/ ByRef规范的一种方式。我什么意思 考虑以下示例:

Public Sub TestMe()

    Dim var1 As Long: var1 = 1
    Dim var2 As Long: var2 = 1

    IncrementByVal (var1)
    IncrementByRef (var2)

    Debug.Print var1, var2

End Sub

Public Function IncrementByVal(ByVal a As Variant) As Variant
    a = a + 100
    IncrementByVal = a
End Function

Public Function IncrementByRef(ByRef a As Variant) As Variant
    a = a + 100
    IncrementByRef= a
End Function
Run Code Online (Sandbox Code Playgroud)

正如你可能看到的,var1var2回报1,而var2应该是101,就因为它是ByRef。该Call-word那种-的改善VBA这个“功能”,但它变得太复杂时,括号内重写要记住ByRef,当没有,读代码的时候。因此,有3个案例相当多:

Public Sub TestMe()

    Dim var1 As Long: var1 = 1
    Dim var2 As Long: var2 = 1
    Dim var3 As Long: var3 = 1
    Dim var4 As Long: var4 = 1
    Dim var5 As Long: var5 = 1
    Dim var6 As Long: var6 = 1

    IncrementByVal (var1)           '1
    IncrementByRef (var2)           '1
    IncrementByVal var3             '1
    IncrementByRef var4             '101
    Call IncrementByVal(var5)       '1
    Call IncrementByRef(var6)       '101

    Debug.Print var1, var2
    Debug.Print var3, var4
    Debug.Print var5, var6

End Sub

Public Function IncrementByVal(ByVal a As Variant) As Variant
    a = a + 100
    IncrementByVal = a
End Function

Public Function IncrementByRef(ByRef a As Variant) As Variant
    a = a + 100
    IncrementByRef = a
End Function
Run Code Online (Sandbox Code Playgroud)

  • 感谢@Vityata,我认为您的意思是函数中的a = a + 100(至少对于ByRef是这样)。我喜欢您要提出的观点,但仍然认为使用`Call`会减少混乱,而不是(只要您永远不要只使用`function(args)`)。但是,我可以理解为什么有些人会认为弃用,因为人们对此不满意。 (2认同)
  • “直到记住括号要替代ByRef时,而不是括号时,以及阅读代码时,都很难记住。”-只有在您了解该语言的工作原理,或者至少是[隐式]调用语句之后,才能记住它。在此之前,“通话”只不过是拐杖……实际上阻碍了这种理解。好奇您对我的回答有何看法,以及在星期六早晨问这个问题有多可惜!我差点错过! (2认同)
  • 您将“Call”所需参数的括号混为一谈,并使用括号来覆盖“ByRef”。它们不是同一件事,一个与另一个无关。这可以通过您未使用 Call 来证明:“Call IncrementByRef((var6))”将处理“ByVal” (2认同)