flow.
"Flow is a condition of deep, nearly meditative involvement." - Tom DeMarco

Do you know the difference between & and && ?

Thursday, March 08, 2007 4:50 PM
Every C# programmer knows that you can concatenate conditional statements using &&.  Many programmers also know that there is an interesting side effect to this: the second conditional statement (the statement on the right of the &&) will not be executed if the first conditional statement is false.  Take the following example...

    public class MilkAndCookies
    {
        public bool GotMilk()
        {
            Console.WriteLine("Oh no!  We're all out of milk!");
            return false;
        }

        public bool GotCookies()
        {
            Console.WriteLine("But we've got plenty of cookies!");
            return true;
        }
    }

    public class Program
    {
        static void Main(string[] args)
        {
            MilkAndCookies milkAndCookies = new MilkAndCookies();

            if (milkAndCookies.GotMilk() && milkAndCookies.GotCookies())
            {
                Console.WriteLine("Milk and Cookies for everyone!");
            }
        }
    }

    // Outputs...
    //
"Oh no!  We're all out of milk!"

In this snippet, only the first statement is actually executed since it returns false.  This effect, known as short circuiting, is a result of the C# compiler optimizing your code based on a principle in boolean algebra.  According to the definition of a boolean AND, the AND is only valid if both arguments given to the operator return true.  For example...

    true = true AND true
    false = true AND false
    false = false AND true
    false = false AND false


Essentially what is happening is that the compiler is taking advantage of the fact that for a && to properly return true, that both conditionals must return true as well.  Therefore, once the first conditional has failed this test this is impossible.  There is no need to evaluate the second conditional at this point.
In fact, if we look at the IL generated by the C# compiler we can see exactly why our code performs as so...

  IL_0001:  newobj     instance void MilkAndCookies.MilkAndCookies::.ctor()
  IL_0006:  stloc.0
  IL_0007:  ldloc.0
  IL_0008:  callvirt   instance bool MilkAndCookies.MilkAndCookies::GotMilk()
  IL_000d:  brfalse.s  IL_001a
  IL_000f:  ldloc.0
  IL_0010:  callvirt   instance bool MilkAndCookies.MilkAndCookies::GotCookies()
  IL_0015:  ldc.i4.0
  IL_0016:  ceq
  IL_0018:  br.s       IL_001b
  IL_001a:  ldc.i4.1
  IL_001b:  stloc.1
  IL_001c:  ldloc.1
  IL_001d:  brtrue.s   IL_002c
  IL_001f:  nop
  IL_0020:  ldstr      "Milk and Cookies for everyone!"
  IL_0025:  call       void [mscorlib]System.Console::WriteLine(string)

Take a look at the statement highlighted in red, this statement tells us to jump to instruction IL_001(about six lines down) if the value on the top of the stack is false.  In effect, this completely skips execution of GotCookies().

As best practices stress that you should not place anything more than state checkers inside of a conditional statement, this behavior does yield some sneaky side effects if you are depending on some sort of operation in your second conditional to be performed.

        public bool GotCookies()
        {
            Console.WriteLine("But we've got plenty of cookies!");

            // Since we have cookies, we should get the plates
            GetThePlates();

            return true;
        }

In our example, GetThePlates() will never be executed since GotMilk() returns false and GotCookies() is short circuited out.  This is also a good example of poor separation of concerns since not only does GotCookies() perform more than one task, it also doesn't convey properly to the user that it will get the plates as well.  By this token, we can see that proper separation of concerns eliminates the possibility of many of these side effects.

Not many C# programmers know this, but you can actually subvert this optimization by using the & instead.  This operator, normally reserved for bitwise operations, can actually be used interchangeable with the &&.  Well, almost interchangeably...the fact is that there is one subtle difference between the two:  the & operator does not short circuit.  Returning to our first example, if we replace the && with & then we actually see the following output...

    public class Program
    {
        static void Main(string[] args)
        {
            MilkAndCookies milkAndCookies = new MilkAndCookies();

            if (milkAndCookies.GotMilk() & milkAndCookies.GotCookies())
            {
                Console.WriteLine("Milk and Cookies for everyone!");
            }
        }
    }

    // Outputs...
    //
"Oh no!  We're all out of milk!"
    // "But we've got plenty of cookies!"

Now if the examine the IL for this method, we can see that execution doesn't bail just because the first condition fails...

  IL_0001:  newobj     instance void MilkAndCookies.MilkAndCookies::.ctor()
  IL_0006:  stloc.0
  IL_0007:  ldloc.0
  IL_0008:  callvirt   instance bool MilkAndCookies.MilkAndCookies::GotMilk()
  IL_000d:  ldloc.0
  IL_000e:  callvirt   instance bool MilkAndCookies.MilkAndCookies::GotCookies()
  IL_0013:  and
  IL_0014:  ldc.i4.0
  IL_0015:  ceq
  IL_0017:  stloc.1
  IL_0018:  ldloc.1
  IL_0019:  brtrue.s   IL_0028
  IL_001b:  nop
  IL_001c:  ldstr      "Milk and Cookies for everyone!"
  IL_0021:  call       void [mscorlib]System.Console::WriteLine(string)

Note the absence of our brfalse.s statement from before.  Execution proceeds as normal regardless of the return value of GotMilk().

As said before, it's really not recommended to write any code that depends on code inside of conditional evaluations being executed.  It's best to either avoid this sort of code altogether, or just move it outside of the conditionals like so...

    public class Program
    {
        static void Main(string[] args)
        {
            MilkAndCookies milkAndCookies = new MilkAndCookies();

            bool gotMilk = milkAndCookies.GotMilk();
            bool gotCookies = milkAndCookies.GotCookies();
            if (gotMilk && gotCookies)
            {
                Console.WriteLine("Milk and Cookies for everyone!");
            }
        }
    }

    // Outputs...
    //
"Oh no!  We're all out of milk!"
    // "But we've got plenty of cookies!"


However, in the event that you encounter legacy or third party code that seems to make use of this 'technique', this is a pretty good tip to remember.

Addendum (3.21.07):
Also remember that this same principle applies to the OR operators as well.  || will perform a short circuiting operation where as | will fully evaluate the conditional regardless of the return value of the first operand.  Keep in mind, however, that since we're looking for an OR here we're actually interested in whether or not the first operand is true, not false.  Therefore, if the first operand evaluates to true then your conditional will short circuit if you're using the || operator.  If your first operand evaluates to false then both conditionals will be evaluated since there is still the possibility of the || returning true if the second conditional returns true.

Special thanks to
Kalpesh for mentioning this case.
 


kick it on DotNetKicks.com

Feedback

 re: Do you know the difference between & and && ?

Dude, your syntax highlighting is terrible. 3/19/2007 8:53 AM | ughh my eyes !

 re: Do you know the difference between & and && ?

" false = false AND false*
*Note that were this a traditional truth table, this case would actually return true since both arguments to the AND operator agree."

I think you're confused. false AND false is always false, as the link you provide confirms...
3/19/2007 4:29 PM | Chris

# re: Do you know the difference between & and && ?

Oops! Good catch, Chris! Looks like I was looking at the wrong column. I thought that was a bit weird when I saw that, that's actually why I made the special note :)

Thanks for pointing that out! 3/19/2007 9:57 PM | Jeremy

# re: Do you know the difference between & and && ?

ughh my eyes ! ,

haha, nice! Yeah, I know. I lost my "copy source as HTML" thingy and have been roughing it by hand ever since. I think the "green" that I used for the known class names has got to go. Are there any of the other colors that are totally off? Let me know and I'll banish them as well in the next article :)

Thanks! 3/19/2007 9:59 PM | Jeremy

 re: Do you know the difference between & and && ?

Coming from the C and C++ world, we were taught never to assume the order of execution of functions placed in an "if" statement. Is this behaviour defined in the C# documentation? Is it possible this might change in future versions? If not, it would be dangerous to use this feature, IMO. 3/21/2007 9:53 AM | Keith

 re: Do you know the difference between & and && ?

Keith: In section 14.11 of the C# Standard, it states that "The operation x && y corresponds to the operation x & y, except that y is evaluated only if x is true.". I assume that this implies that the evaluation is always left to right.

I found the ECMA-334 standard at http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-334.pdf. 3/21/2007 11:13 AM | David

# re: Do you know the difference between & and && ?

This behavior is actually documented but I suppose that's no guarantee that it will not change in the future. (Search your local MSDN for '&&' filtered by C# and you'll see the explanation in the first line of the docs). You're completely correct in stating that this is a dangerous feature, it really is. Perhaps I should have made it clearer in my post but this technique should never be relied upon. I bring it up here purely for educational purposes in case someone should run into it in legacy code.

It's actually my understanding that VB.NET doesn't perform this optimization. Apparently it was in beta versions of .NET but broke so much legacy code that it had to be removed.

This actually brings up another interesting point that's worth mentioning. This technique, as well as many of the other techniques that I discuss on this site, rely on assumptions made by the .NET C# compiler. This particular case is actually a compiler level optimization, if you are using a non Microsoft compiler your mileage may vary. 3/21/2007 11:15 AM | Jeremy

# re: Do you know the difference between & and && ?

David,

Thanks for finding this, I think we commented at the same time so I missed your response :)

If this is actually in the ECMA spec than I suppose I was mistaken in my previous statement that this behavior may be compiler specific. This should work on any compiler.

Thanks again for finding this!

:) 3/21/2007 11:17 AM | Jeremy

 re: Do you know the difference between & and && ?

I was talking about this to a friend yesterday.
Also, include use of | and || (along-with Enum)

Thanks for the post :) 3/21/2007 11:25 AM | Kalpesh

# re: Do you know the difference between & and && ?

Keith (& Jeremey)

Short-Curcuiting has been part of C-based lanuages since the original Kerignhan & Ritchie C compiler of the early 80s. IT WILL NOT CHANGE.

It is not dangerous to use this, as the feature was specifically added to the langauge. The typical usage would be:
if (obj != null && obj.Length > 0)
Obviously, if obj was null, the second half would throw a null reference exception, but with && is is safe.

(However, even if it were just a new C# feature, since it's been defined in the specification document, you can also be assured that it would never change. There are way too many companies waiting to sue Microsoft saying "your change broken my program" for them to try anything like that)

In C & C++, the places where you cannot trust the order of operations would be in arithmatic expressions:

A=func1() + func2();

and function parameters

func(func1(), func2());

In either of the above, func1() could be called before or after (or even concurrently with) func2())

As for the & operator, it's not "normally reserved for bitwise operations" -- It's ALWAYS for bitwise operations. The compiler just converts the boolean values in integers. When you wrote:
if (GotMilk() & GotCookies())
. . . GetPlates();
you are effectively writing:
int b1, b2;
if (GetMilk())
. . . b1 = 1;
else
. . . b1 = 0;

if (GetCookies())
. . . b2 = 1;
else
. . . b2 = 0;

if( b1 & b2)
. . .GetPlates();
(dots added in the above for text alignment)



3/21/2007 1:32 PM | James Curran

# re: Do you know the difference between & and && ?

James,

Thanks for the clarification. I had actually never considered the possibility of checking an object for null before checking a property on it. That's pretty clever :) 3/21/2007 1:46 PM | Jeremy

# re: Do you know the difference between & and && ?

Kalpesh,

I'm glad you liked the article. Thanks for the reminder about the | operator. I'll be sure to make an addendum to the article.

Thanks again!
Jeremy 3/21/2007 1:47 PM | Jeremy

 re: Do you know the difference between & and && ?

I think you need a spam filter. Useful little article, though. Thank you. 9/7/2007 11:08 AM | Michael

 re: Do you know the difference between & and && ?

thanks for refreshing my memory 6/1/2008 8:03 AM | Sunil

Post a comment





 

Please add 4 and 3 and type the answer here: