Friday, November 30, 2007

OrElse in VB.NET

Whenever possible, always use the VB.NET keyword OrElse operator rather than the vanilla-flavored (and inefficient) Or.

Consider the following line of code:
Dim Counter As Integer
Dim x As Integer = 0
Dim y As Integer = 5
Dim z As Integer = 9
Dim q As Boolean

For Counter = 0 To 100000000
   If x = 0 Or y <= 5 Or z >= 9 Or z - y <= 4 Then
      q = True
   End If
Next
This code took 2.53 seconds to execute.

Here's the same code, except using the OrElse operator:
Dim Counter As Integer
Dim x As Integer = 0
Dim y As Integer = 5
Dim z As Integer = 9
Dim q As Boolean

For Counter = 0 To 100000000
   If x = 0 OrElse y <= 5 OrElse z >= 9 OrElse z - y <= 4 Then
      q = True
   End If
Next
This code took just 1.73 seconds.

Why the difference?

Well, when the Or operator is used, VB.NET evaluates every expression in a statement, even though it doesn't need to. In the Or example above, after VB.NET has determined that x=0 (thus assuring the entire statement will evaluate to true), it will still evaluate each expression that follows (y<=5, z>=9, z-y<=4), even though the results of those evaluations will not change the final outcome.

On the other hand, the OrElse operator works exactly the way you expect it to. As soon as VB.NET encounters the OrElse keyword, any remaining code is bypassed if the code preceding it evaluates to true (which, in this case, would be 'x=0').

This behavior, called "short-circuiting," is really the way the Or keyword should have worked in VB in the first place (and, indeed, does in some other programming languages).

And the difference in efficiency can be even greater than the numbers reflected above. It really all depends on 1) The number of evaluations that have to be performed, and 2) How early in the statement an expression evaluates to true. In truth, using OrElse can be up to 100 times faster or more, depending upon what follows it in the statement.

In every case, short-circuiting will improve performance, especially when the code being bypassed is complex or involves procedure calls.

So use it -- OrElse!

No comments: