Does (cond1 && cond2 && cond3) always evaluate left to right?

  • Thread starter Thread starter orekinbck
  • Start date Start date
O

orekinbck

Hi There

Say I want to check if object1.Property1 is equal to a value, but
object1 could be null.

At the moment I have code like this:

if (object1 != null)
{
if (object1.Property == desiredValue)
{
//Do work here
}
}

Here is my question - Can I do this ...

if (object1 != null && object1.Property == desiredValue)
{
//Do work here
}

.... and be sure that conditions are always evaluated left to right and
the evaluation stops as soon as a condition evaluates to false ?

If I can collapse the conditions into one if statement, do you think
this is more or less elegant coding?

TIA
Bill
 
Yes, you can.
The statements are evalueated from left to right. The most right condition
is not evaluated when one of the former conditions evaluates to false.
 
James Curran said:
Also, nte that this behavior was specified in the original C language
definition, and carried over into C++, Java and C#. This is not
particular
to one specific compiler, but a requirement for any compiler implementing
any of the C family of langauges.

--

Another note:

Although this is a C# group, I'm just pointing out that a similar method is
available in VB.Net as well:

Dim a As TextBox = Page.FindControl("MyControl")

If Not a Is Nothing And a.Text <> String.Empty
a.Text = "This is NOT empty!"
End If

The above would throw an exception (if a is nothing) because the "And"
keyword does not short-circuit the "If" statement. In order to
short-circuit in VB.Net you would use the keywords "AndAlso" or "OrElse".

Dim a As TextBox = Page.FindControl("MyControl")

If Not a Is Nothing AndAlso a.Text <> String.Empty
a.Text = "This is NOT empty!"
End If


HTH,
Mythran
 
(Yet another) note: C# also has operators & and | that do not perform
McCarthy evaluation (short-circuit). I'm not 100% sure, but I would
suspect that there is no guarantee in these cases that they evaluate
left-to-right.

&& and || will always stop as soon as the result of the expression is
determined. For && that means as soon as something evaluates false; for
|| that means as soon as something evaluates true, left-to-right.
 
Bruce Wood said:
(Yet another) note: C# also has operators & and | that do not perform
McCarthy evaluation (short-circuit). I'm not 100% sure, but I would
suspect that there is no guarantee in these cases that they evaluate
left-to-right.

Consider:
if(MethodThatThrowsException() == true & MethodThatSetsVariable() == true)

The expected behaviour would be that MethodThatSetsVariable would not
execute.
 
Bruce Wood said:
(Yet another) note: C# also has operators & and | that do not perform
McCarthy evaluation (short-circuit). I'm not 100% sure, but I would
suspect that there is no guarantee in these cases that they evaluate
left-to-right.

Yes there is:

From the C# spec section 14.2.1 (ECMA numbering):

<quote>
Except for the assignment operators, all binary operators are left-
associative, meaning that operations are performed from left to right.
[Example: For example, x + y + z is evaluated as (x + y) + z. end
example]
</quote>

This is different to C/C++, which makes no such guarantee.
&& and || will always stop as soon as the result of the expression is
determined. For && that means as soon as something evaluates false; for
|| that means as soon as something evaluates true, left-to-right.

Yup.
 
Thanks, Jon. You can tell I'm an old C hack, which is why I wasn't sure
about & and |. Nice to know that C# firmed that up.
 
Sean Hederman said:
Consider:
if(MethodThatThrowsException() == true & MethodThatSetsVariable() == true)

The expected behaviour would be that MethodThatSetsVariable would not
execute.

Yes it would - the above does *not* do short-circuiting, whereas with a
&& the RHS wouldn't execute.
 
Jon,

You missed Sean's point. Look at the method names. The left-hand side
would throw an exception, which would interrupt the control flow and so
the right-hand side would not execute.

However, you are correct: if the left-hand side did not throw an
exception then the right-hand side would always execute regardless of
to what value the left-hand side evaluated.
 
Bruce Wood said:
You missed Sean's point. Look at the method names. The left-hand side
would throw an exception, which would interrupt the control flow and so
the right-hand side would not execute.

Ah, right. Yes, I did miss that completely :)
However, you are correct: if the left-hand side did not throw an
exception then the right-hand side would always execute regardless of
to what value the left-hand side evaluated.

Yup.
 
Mythran said:
Another note:

Although this is a C# group, I'm just pointing out that a similar
method is available in VB.Net as well:
The above would throw an exception (if a is nothing) because the "And"
keyword does not short-circuit the "If" statement. In order to
short-circuit in VB.Net you would use the keywords "AndAlso" or "OrElse".

How utterly vile.

I'd forgotten about that whole bunfight over backwards compatibility
with VB6.
 
Except for the assignment operators, all binary operators are left-
associative, meaning that operations are performed from left to right.
[Example: For example, x + y + z is evaluated as (x + y) + z. end
example]
&& and || will always stop as soon as the result of the expression is
determined. For && that means as soon as something evaluates false; for
|| that means as soon as something evaluates true, left-to-right.

Yup.
Actually C/C++ does guarantee this. But operator precedence takes over as it
does in C# as well. 1 + 4 * 2 does not equal 10 in either language. If all
operators are equal precedence they will evaluate left to right just like
func1() && func2() will short circuit in C#/C++/C. Just because operator
precedence is not understood does not mean that C/C++ will evaluate from
right to left.
 
Lorad said:
Actually C/C++ does guarantee this. But operator precedence takes over as it
does in C# as well. 1 + 4 * 2 does not equal 10 in either language. If all
operators are equal precedence they will evaluate left to right just like
func1() && func2() will short circuit in C#/C++/C. Just because operator
precedence is not understood does not mean that C/C++ will evaluate from
right to left.

I was under the impression (and it's one which I've seen repeated in
several places by knowledgable people) that although most individual
compilers specify the order of evaluation, it's not in the standard.

Reading Stroustrup (2nd ed) I can find where , && and || guarantee that
the left-hand operand is evaluated before the right-hand operand, but
nothing more than that. The fact that those ones are *specifically*
guaranteed implies to me that the rest aren't.
 
You are arguing two different things. Consider:

int One() { printf ("1"); return 1;}
int Two() { printf ("2"); return 2;}
int Four() { printf ("4"); return 4;}

int x = One() + Four() * Two();

In C/C++:
We CAN be absolutely certain that afterwards, x will equal 9.
We CANNOT be absolutely certain that "142" will be printed. It may print
"421", "214" etc.

However, in C# I believe we can assume that "142" will be printed (assuming
appropriate changes to the output routine were made).

The individual terms will be evaluated in any order, while the expression as
a whole will be evaluated according to precedence. Further in C/C++ (but,
again, not in C#), the compiler may assume infinite precision, and ignore
redundant parentheses.:

int a = (x * y) / z;

The compiler is allowed to that as "a = x * (y / z)", which is
equivalent --- unless y is small and z large, so that (y/z) goes to zero in
an int.

--
Truth,
James Curran
[erstwhile VC++ MVP]

Home: www.noveltheory.com Work: www.njtheater.com
Blog: www.honestillusion.com Day Job: www.partsearch.com
 
James Curran said:
You are arguing two different things. Consider:

int One() { printf ("1"); return 1;}
int Two() { printf ("2"); return 2;}
int Four() { printf ("4"); return 4;}

int x = One() + Four() * Two();

In C/C++:
We CAN be absolutely certain that afterwards, x will equal 9.
We CANNOT be absolutely certain that "142" will be printed. It may print
"421", "214" etc.
Yes.

However, in C# I believe we can assume that "142" will be printed (assuming
appropriate changes to the output routine were made).
Yes.

The individual terms will be evaluated in any order, while the expression as
a whole will be evaluated according to precedence. Further in C/C++ (but,
again, not in C#), the compiler may assume infinite precision, and ignore
redundant parentheses.:

int a = (x * y) / z;

The compiler is allowed to that as "a = x * (y / z)", which is
equivalent --- unless y is small and z large, so that (y/z) goes to zero in
an int.

I'm not sure where this comes into our discussion though - I was just
saying that C# *does* guarantee that

x & y

will evaluate x first, then y - but that C/C++ makes no guarantee.

Lorad was claiming that if all the operators are of equal precedence,
C/C++ guarantee that the operands are evaluating from left to right. I
believe that's true of && and ||, but not of other operators.
Precedence will still be obeyed in terms of the operations themselves,
but the order in which the operands are evaluated is an entirely
separate matter.
 
Back
Top