VBA不支持短路
据称VBA不支持短路,因为它只具有位And/Or/Not等操作。根据VBA语言规范:"逻辑运算符是对操作数执行按位计算的简单数据运算符。"考虑到这一点,使用true =&H1111
和false =&H0000
来设计VBA是有意义的:这样逻辑语句就可以作为按位运算进行评估。
缺乏短路会导致问题
性能:当评估此语句时,
ReallyExpensiveFunction()
将始终运行,即使左侧条件的结果并不需要它If IsNecessary() And ReallyExpensiveFunction() Then '... End If
错误:如果MyObj为Nothing,则此条件语句将导致运行时错误,因为VBA仍然会尝试检查
Property
的值If Not MyObj Is Nothing And MyObj.Property = 5 Then '... End If
我使用的解决方案是嵌套If
语句来实现短路行为
If cond1 And cond2 Then
'...
End If
成为If cond1 Then
If cond2 Then
'...
End If
End If
这种方式使得 If 语句具有类似短路的行为,如果 cond1
为 False
,则不必评估 cond2
。
如果有 Else 子句,则会创建重复的代码块
If Not MyObj Is Nothing And MyObj.Property = 5 Then
MsgBox "YAY"
Else
MsgBox "BOO"
End If
成为If Not MyObj Is Nothing Then
If MyObj.Property = 5 Then
MsgBox "YAY"
Else
MsgBox "BOO" 'Duplicate
End If
Else
MsgBox "BOO" 'Duplicate
End If
有没有一种方法可以重新编写If
语句以保留短路行为,但避免代码重复?
也许可以使用另一个分支语句,比如Select Case
?
为了给问题添加背景,这里是我关注的特定情况。我正在实现一个哈希表,通过在链表中链接它们来处理冲突。底层数组大小被强制为2的幂,并且散列值通过将其截断为适当的长度分布到当前数组大小中。
例如,假设数组长度为16(二进制为10000)。如果我有一个散列到27(二进制为11011)的键,则可以通过仅保留该数组大小限制内的位来将其存储在我的16个插槽数组中。此项目将存储的索引是(散列值)And(数组长度-1)
,在本例中为(二进制11011)And(1111)
,即1011
,即11。实际的哈希码与键一起存储在插槽中。
在哈希表中查找项的时候,必须检查哈希和键以确定已找到正确的项。但是,如果哈希不匹配,则没有理由检查键。我希望通过嵌套If来获得短路行为,以获得微小而难以捉摸的性能提升:
While Not e Is Nothing
If keyhash = e.hash Then
If Key = e.Key Then
e.Value = Value
Exit Property
Else
Set e = e.nextEntry
End If
Else
Set e = e.nextEntry
End If
Wend
你可以看到 Set...
是重复的,因此出现了这个问题。
SET
这一行移到if语句外面,在while循环中放在最后一行之前呢?除了退出时不设置之外,其他时候都需要设置。顺便说一下,问得好! - Ioannis