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.]
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.
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.
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).
We keep talking about a lazy IIF (equivalent to the ternary operator ?: in C#/C/C++), so one of these days you might get your wish!
Hmm, were any of you familiar with ADA?
I remember the keyword pairs AND THEN and OR ELSE from my college days (where the Language Ordained From On High was Ada 95).
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? ๐
Thanks for pointing out my error! I’ve fixed it now…
Pingback: .Net Blog
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?
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.
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?
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?
@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
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.
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… ๐
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.
Pingback: Anonymous
Pingback: difference between And and AndAlso in VB.net | Coding and Programing
Pingback: How to: What is the difference between And and AndAlso in VB.net? | SevenNet
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
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.
Pingback: VB.NET์์ And์ AndAlso์ ์ฐจ์ด์ ์ ๋ฌด์์ ๋๊น? - ์คํํ๋ก์ฐ