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

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
 
G

Guest

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.
 
M

Mythran

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
 
B

Bruce Wood

(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.
 
S

Sean Hederman

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.
 
J

Jon Skeet [C# MVP]

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.
 
B

Bruce Wood

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.
 
J

Jon Skeet [C# MVP]

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.
 
B

Bruce Wood

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.
 
J

Jon Skeet [C# MVP]

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.
 
S

Steve Walker

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.
 
L

Lorad

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.
 
J

Jon Skeet [C# MVP]

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.
 
J

James Curran

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
 
J

Jon Skeet [C# MVP]

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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top