The Ballad of AndAlso and OrElse

Last week, Rachel posted an entry talking about AndAlso and OrElse. Besides Integer and array bounds, this has got to be one of the most sensitive changes we made to the language in VB .NET 2002. So I thought I’d talk a little bit about it.

Prior to VB.NET, the VB language only had the And and Or operators. They were essentially bitwise operators, which means that they took their two operands and performed an AND or OR operation on each bit position to produce the resulting bit. So 3 Or 4 = 7, and 2 And 4 = 0. At the same time, the Boolean value True was considered to be equivalent to the value -1, which is just a 1 in each bit position. As a result, the bitwise operators behaved as if they were logical operators when working on Boolean values. So True And False = False, and True Or False = True. And if you mixed and matched Boolean and numeric values, things pretty much worked the way you’d expect them to. So True And 4 = 4, and 10 Or False = 10.

This all worked pretty well, and avoided the situation you have in languages like C where there are separate logical operators (|| &&) and bitwise operators (| &). However, there were some problems. The biggest was that it was not possible to support short-circuiting behaviors when doing logical AND and OR operations. Short circuiting is fantastically useful, especially when dealing with reference types. It is extremely common to want to write code along the lines of:

If (Not x Is Nothing) And (x.y = 10) Then
...
End If

Without short circuiting, though, this code will throw an exception if x is Nothing, because both sides of the operation are always evaluated. (Having learned about the usefulness of short circuiting from other languages, this limitation bit me all the time when I was working in VB, and I even saw quite a few bugs like this created by people who knew nothing about short circuiting but just expected it to “do the right thing.”)

One of the things we wanted to do in VB.NET, then, was add short circuiting logical operations. A way of doing it would have been just to have changed the meaning of And and Or if the two operands were typed as Boolean, but this seemed a very unacceptable solution. In general, it is very bad to overload two very different behaviors on top of the same keyword. In other words, without knowing what the result type of Foo() and Bar() were, it would be hard to know what the behavior of

If Foo() And Bar() Then
...
End If

would be. Would Bar() always be evaluated or would it sometimes not be evaluated? Even worse, the behavior of the expression might change drastically by shifting the type of just one of the operands.

The only other alternative, then, was to introduce new operators. Our first thought was that logical operations are much more common than bitwise operations, so we should make And and Or be logical operators and add new bitwise operators named BitAnd, BitOr, BitXor and BitNot (the last two being for completeness). However, during one of the betas it became obvious that this was a pretty bad idea. A VB user who forgets that the new operators exist and uses And when he means BitAnd and Or when he means BitOr would get code that compiles but produces “bad” results. For example:

If 2 And 4 Then
...
End If

Assuming Option Strict was off, this would produce the value True (or -1) instead of the value False (or 0), as it did in previous versions. Given that this would be a very easy error for programmers to make and it would have an effect that could be very hard to track down and understand, it seemed clear to us that changing the meaning of these operators would be untenable.

That left the option of adding new logical operators, and we spent a lot time thinking about potential new keywords. I think I’ll do a whole entry later just on the question of choosing new keywords, but suffice it to say that AndAlso and OrElse were the best choices, in our humble opinions. Ironically, we’re not even the first language to use those names in this way – the functional language ML has andalso and orelse operators, too. (I don’t think we were aware of that at the time we were choosing the keywords, although I could be wrong about that.)

People seem to enjoy poking fun at the keywords, but after working with them for a while, I think they work pretty well and were the right way to add the new feature to the language without breaking people in bizarre and unexpected ways. Then again, as always, I’m biased…

[Correction 09/15/03: Fixed small math error pointed out by Stuart, below.]

21 thoughts on “The Ballad of AndAlso and OrElse

  1. Steve Hiner

    All is forgiven. I take back every complaint I used to have about the change from Beta 1 to Beta 2. Now I see it was the right choice – it just felt so wrong without all that background info.

    Reply
  2. karl

    I too was bit in the ass more than a few times with the lack of short-circuit operators. I think they are a great addition to vb.net…and i think the OrElse/AndAlso, while funny, convey exactly what will happen (although And/Or also logically convey that meaning). I do think it’s a shame though that people not familiar with short-circuit are likely to overlook these new keywords although it almost always leads to better and more performant code.

    Reply
  3. Jeremy

    I think the names are completely fitting, what would be the alternative, AndAnd, OrOr? =) I am very happy to see VB changing, I just wish there were more lazy operators (How about throwing us a bone with a lazy IIF).

    Reply
  4. Stuart

    Good stuff! I love the AndAlso / OrElse operators, too.

    One thing, though, I believe you have an error in your math. You say about the statement 2 And 4, "Assuming Option Strict was off, this would produce the value True (or -1) instead of the value 4 (as it did in previous versions). " I believe you meant to say this, "Assuming Option Strict was off, this would produce the value True (or -1) instead of the value False (or 0) as it did in previous versions."

    If 2 And 4 has always produced 4 (or True) we are all in deep trouble, no? 😉

    Reply
  5. Pingback: .Net Blog

  6. Jim Anderson

    Wouldn’t you always want to use AndAlso or OrElse instead of And or Or since And or Or will always evaluate both expressions even if it isn’t necessary while AndAlso or OrElse will short-circuit if possible?

    Reply
    1. Sachin Kainth

      Jim,

      I don’t think you would always want to short circuit and the reason for this is that sometimes your second operand may be a method call and that method call may execute some code that you may want to execute regardless of whether the method returns true or false.

      Reply
      1. Patrick Chasco

        Sachin,

        That would be very poor application design, in my opinion. I believe that a call to a method that will have side effects should be very explicitly called, not hidden within the operands of an expression in an if statement.

        If the function is to be called no matter what, shouldn’t it be called before the if statement and its result saved in a variable?

        Reply
  7. Steve Fewell

    As we’re talking about Ada’s AND THEN and OR ELSE keywords, has anyone noticed that the .NET Exception blocks are similar to those in Ada. Ada has Begin….<Code>….Exception…<Exception Code>…End block styles, while VB.NET has Try…<Code>…Catch…<Code>…End Try blocks! Co-incidence?

    Reply
    1. matt

      @the last post there..

      erm. if youve ever worked with ANY languages that do compartment error catching, then they all follow that pattern:

      try

      //dangerous code

      catch(type of exception)

      //handle error

      catch(different type of exception)

      //handle different error

      finally

      //always do this code

      end

      java, c#.. etc, they all do it

      Reply
  8. Publius

    This doesn’t make any sense. The default operators (&& and ||) in C# are short-circuiting, but the default operators in VB.NET aren’t. There’s no reason for them not to be. If anything, AndAlso makes more sense as "also evaluate this condition whether or not the first one was false". It’s a real pain in the *** to have to type andalso and orelse for 99.9% of my conditional expressions.

    Reply
  9. Rainier

    hmmm… I completely agree. Why not take it a step further and make "Also" another keyword to add to And/Or if you want the next condition to be evaluated too?

    e.g.

    If <condition1> And Also <condition2> Then…

    or…

    If <condition1> Or Also <condition2> Then…

    so instead of introducing two new keywords, you now have just one… to add if the occassion calls for it… 😉

    Reply
  10. Guy Weller

    The argument that changing the nature of the And/Or might lead to an increase in errors is simply untrue. From my experience it would make errors less likely. The truth is that virtually nobody uses bitwise comparisons in VB – if you are working at bit-level you’re going to be using C / Assembler or similar.

    Isn’t there a case for something along the lines of ‘Option ShortCircuit’ to allow developers to choose how and/or are interpreted? I’m willing to bet that like Option Explicit everyone would always specify it.

    Reply
  11. Pingback: Anonymous

  12. Pingback: difference between And and AndAlso in VB.net | Coding and Programing

  13. Pingback: How to: What is the difference between And and AndAlso in VB.net? | SevenNet

  14. el correky

    Or/And will always evaluate both1 the expressions and then return a result. They are not short-circuiting.

    OrElse/AndAlso are short-circuiting. The right expression is only evaluated if the outcome cannot be determined from the evaluation of the left expression alone. (That means: OrElse will only evaluate the right expression if the left expression is false, and AndAlso will only evaluate the right expression if the left expression is true.)

    Assuming that no side effects occur in the expressions and the expressions are not dependent (and any execution overhead is ignored), then they are the same.

    However, in many cases it is that the expressions are dependent. For instance, we want to do something when a List is not-Nothing and has more than one element:

    If list IsNot Nothing AndAlso list.Length > 0 Then .. ‘list has stuff
    This can also be used to avoid an “expensive” computation (or side-effects, ick!):

    If Not Validate(x) OrElse Not ExpensiveValidate(x) Then .. ‘not valid
    Personally, I find that AndAlso and OrElse are the correct operators to use in all but the 1% – or less, hopefully! – of the cases where a side-effect is desired.

    Happy coding.

    1 An Exception thrown in the first expression will prevent the second expression from being evaluated, but this should hardly be surprising ..

    shareimprove this answer
    edited Nov 21 ’12 at 8:46
    answered Dec 7 ’11 at 1:56
    user166390
    add a comment
    up vote
    9
    down vote
    Besides the short-circuiting mentioned in the other answers, Or/And are usable as bitwise operators where OrElse/AndAlso are not. Bitwise operations include combining values of Flags enums, such as the FileAttributes enumeration where you might indicate a file is both read only and hidden by FileAttributes.ReadOnly Or FileAttributes.Hidden

    shareimprove this answer
    answered Dec 7 ’11 at 4:07

    Gideon Engelberth
    5,06111018
    add a comment
    up vote
    4
    down vote
    The difference is that OrElse and AndAlso will short-circuit based on the first condition, meaning that if the first condition doesn’t pass, the second (or more) conditions will not be evaluated. This is particularly useful when one of the conditions might be more intensive than the other.

    Example where Or is fine (both conditions evaluated):

    If Name = “Fred” Or Name = “Sam” Then
    It really doesn’t matter which way around they are evaluated

    The following AndAlso is useful because the second condition might fail

    If Not SomeObject Is Nothing AndAlso CheckObjectExistsInDatabase(SomeObject) Then
    This allows for the first condition to check whether the object has been set and only if it has been set will go and check the database (or some other task). If this had been a plain And keyword, both would be evaluated.

    shareimprove this answer
    answered Dec 7 ’11 at 2:00

    davidsleeps
    5,45884266
    add a comment
    up vote
    2
    down vote
    @Gideon – glad someone pointed that out. Here is a simple test that shows the dramatic impact of AndAlso:

    Dim tm As New Stopwatch
    Const tries As Integer = 123456
    Dim z As Integer = 0
    Dim s() As String = New String() {“0”, “one”}

    Debug.WriteLine(“AndAlso”)
    For x As Integer = 0 To s.Length – 1
    z = 0
    tm.Restart() ‘restart the stopwatch
    For y As Integer = 0 To tries
    If s(x) = x.ToString AndAlso s(x) = y.ToString Then ‘<<<<<<<<<<
    z += 1
    End If
    Next
    tm.Stop()
    Debug.WriteLine(x.ToString.PadRight(3, " "c) & z.ToString.PadRight(10, " "c) & tm.Elapsed.ToString)
    Next

    Debug.WriteLine("And")
    For x As Integer = 0 To s.Length – 1
    z = 0
    tm.Restart() 'restart the stopwatch
    For y As Integer = 0 To tries
    If s(x) = x.ToString And s(x) = y.ToString Then '<<<<<<<<<<
    z += 1
    End If
    Next
    tm.Stop()
    Debug.WriteLine(x.ToString.PadRight(3, " "c) & z.ToString.PadRight(10, " "c) & tm.Elapsed.ToString)
    Next

    Reply
  15. Dave F.

    I would think that using && and || as new short-circuited operators would be more practical. They’re terse, quick to type, and people are already familiar with them from other languages. ‘And’ and ‘Or’ would probably fall out of use as logical operators and just be used for bit-wise operators.

    As for people wanting to use non-short-circuiting logical operators, I agree with Patrick Chasco; it would be like doing this in other languages:

    if( first() | second() ) {…}

    which isn’t good practice. It’s better to do:

    firstvar = first();
    secondvar = second();
    if( firstvar || secondvar() ) {…

    and why wouldn’t the same be true for VB? IMHO, always using short-circuited logical operators is clearer, and I would have liked quick, familiar && and ||.

    My 2 cents.

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *