VBA Short-Circuit `And` Alternatives [duplicate]

倾然丶 夕夏残阳落幕 提交于 2019-11-27 02:04:15

As a more general apprach, I suggest to introduce condition flags and make usage of assigning comparison results to booleans:

dim cond1 as boolean
dim cond2 as boolean

cond1 = false
cond2 = false

' Step 1
cond1 = MyObj Is Nothing

' Step 2: do it only if step 1 was sucessful 
if cond1 then
    cond2 = MyObj.Property = 5
end if

' Final result:
if cond2 then
   msgbox "Yay"
else
   msgbox "Boo"
end if

By "chaining" those condition flags, every step is safe, you see the final result in the last condition flag and you don't do unnecessary comparisons. And, to me, it keeps readable.

EDIT 14/09/07

I usually never omit block delimiters and I consequently set every statement of control structures on a new line. But in this case, you can carefully get a very dense notation that reminds on short-circuit notation, also because the VBA compiler initiates the variables:

dim cond1 as boolean
dim cond2 as boolean
dim cond3 as boolean
dim cond4 as boolean

cond1 = MyObj Is Nothing
if cond1 then cond2 = MyObj.Property = 5
if cond2 then cond3 = MyObj.Property2 = constSomething
if cond3 then cond4 = not isNull(MyObj.Property77)

if cond4 then
   msgbox "Hyper-Yay"
else
   msgbox "Boo"
end if

I could agree to this. It's a clear flow to read.

There is a way. You're not guaranteed to like it. But this is one of those carefully constructed cases where Goto comes in handy

If Not MyObj Is Nothing Then
    If MyObj.Property = 5 Then
        MsgBox "YAY"
    Else
        Goto JUMPHERE
    End If
Else
JUMPHERE:
    MsgBox "BOO" 'Duplicate
End If

A short-circuited code to implement a short-circuited condition!

Alternately, if instead of MsgBox "BOO" is some long and convoluted code, it can be wrapped in a function and that can be written twice with minimal impact/overhead.


Regarding the specific use case, the multiple Set operations will have a minimal performance impact and hence, if one wants to avoid using Goto (still the most globally efficient approach, codesize + performance wise, avoiding creation of dummy variables, etc. - won't matter, though for such a small piece of code) there is negligible downside in simply repeating the command.

Just to analyze (your sample code) how much can be gained by different methods...

  • If both conditions are true:, there are 2 comparisons, 1 assignment, 0 jumps
  • If only first condition is true: there are 2 comparisons, 1 pointer-assignment, 1 jump
  • If only second condition is true: there is 1 comparison, 1 pointer-assignment, 1 jump
  • If both conditions are false: there is 1 comparison, 1 pointer-assignment, 1 jump (same as above)

In terms of performance, a jump is usually more expensive than comparison (which happens very quickly in ALU vs. the jump which could lead to a disruption in the code cache, maybe not at these sizes, but still jumps are expensive).

And normal assignment by value would be at best as fast as a pointer-assignment or sometimes worse (this is VBA, can't be 100% sure of the p-code implementation)

So, depending on your use case / expected data, you can try to minimize average number of jumps per iteration in your loop and reorder the code.

How about:

s = "BOO"

If Not MyObj Is Nothing Then
    If MyObj.Property = 5 Then s = "YAY"
End If

MsgBox s
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!