The Coding Monkey

Tuesday, January 17, 2006

Short Circuit Logic

I participated in a small group talk at my company last week on the topic of "Upgrading VB6 to VB.NET". The presenter had scoured the Internet looking for helpful information, and going over pros, cons, and typical problems that people encounter when converting existing code from VB6 to .NET. One of the issues he brought up was with short circuit logic. He found this article on The Scarms (which I never heard of), that said that VB.NET now did short circuit logic where VB6 did not:

New to VB.NET is short circuit logic. Short circuit logic only evaluates multiple conditions in a logical statement if necessary. Consider:

Dim b As Boolean

b = Function1() And Function2()

Under VB6 both functions are evaluated. Under VB.NET if function1 is false, function2 is not evaluated since "b" cannot be True. While this is more efficient it can cause problems. If a side effect of evaluating function2 is the setting of a global variable, that variable will no longer get set. This will produce the desired effect:

Dim b As Boolean
Dim c As Boolean
Dim d As Boolean

c = Function1()
d = Function2()
b = c And d

This is dead wrong. VB.NET by default will still evaluate all terms in a logical expression as it did in VB6. For many VB6 programmers who did a lot of C, this bothered them greatly, and so VB.NET introduced two new keywords to perform short cirucit logic (AndAlso does short circuit And, and OrElse does short circuit Or). However, the operation of And and Or have not changed. Here is an example VB.NET program which illustrates this:

Module VBPlayground

   Sub Main()

      Dim bFirstParam As Boolean = False
      Console.WriteLine("Testing And")
      If (bFirstParam And SecondParam()) Then
         ' Do Nothing
      End If

      Console.WriteLine("Testing AndAlso")
      If (bFirstParam AndAlso SecondParam()) Then
         ' Do Nothing
      End If

      bFirstParam = True
      Console.WriteLine("Testing Or")
      If (bFirstParam Or SecondParam()) Then
         ' Do Nothing
      End If

      Console.WriteLine("Testing OrElse")
      If (bFirstParam OrElse SecondParam()) Then
         ' Do Nothing
      End If


   End Sub

   Private Function SecondParam() As Boolean

      Console.WriteLine("Second Parameter Called")
      Return True

   End Function

End Module

And here is the output from that program:

Testing And
Second Parameter Called
Testing AndAlso
Testing Or
Second Parameter Called
Testing OrElse

So why did the VB.NET folks decide to continue this behavior, instead of bringing it inline with the other .NET languages like C# and J#? The answer is pretty straightforward... backwards compatibility. If they changed the behavior, and you tried to port your code from VB6 to VB.NET, you could potentially run into all sorts of weird bugs that would be difficult to find, since you might depend on the side effects of a function that might never get called. Imagine if some important database call occurred in SecondParam(). Thats why they introduced the new keywords, and I think it makes sense.

However, this is also a good reminder to use AndAlso and OrElse instead of And and Or in your regular Visual Basic programming from now on, unless you have a specific reason for all parameters to be evaluated.


Post a Comment

<< Home