C# Conditional and (&&) or (||) Precedence

C# conditional AND (&&) OR (||) precedence

Change the first false by true. I know it seems stupid to have (true || true) but it proves your point.

bool result = true || true && false;   // --> true 
result = (true || true) && false; // --> false
result = true || (true && false); // --> true

Is order guaranteed in an or expression

Will ListEqualByComparer.TryGetOrCreate always be called before EnumerableEqualByComparer.TryGetOrCreate?

Yes, and as || is short-circuiting, the second call will only be made if the first call returns false.

From the C# 5 specification, section 7.12.1:

When the operands of && or || are of type bool, or when the operands are of types that do not define an applicable operator & or operator |, but do define implicit conversions to bool, the operation is processed as follows:

[...]

The operation x || y is evaluated as x ? true : y. In other words, x is first evaluated and converted to type bool. Then, if x is true, the result of the operation is true. Otherwise, y is evaluated and converted to type bool, and this becomes the result of the operation.

Or and And condition in same IF statement behaves differently

I was too hasty, yet again. The issue has to do with both operator precedence and short-circuit evaluation of the logical condition:

  • because of the precedence, the statement is evaluated as follows:

    (x || (y && z)) ~ (temp1 == "0" || (temp2 == "1" && temp != null))
  • and here the short-circuit evaluation kicks in - because left side of the || operator is already true e.g. temp1 == "0" the right part is simply skipped.

    The operation

    x || y

    corresponds to the operation

    x | y

    except that if x is true, y is not evaluated because the OR operation is true regardless of the value of y. This concept is known as "short-circuit" evaluation.

Confusing example about '&&' and '||' precedence

The expression is short-circuiting. From the link:

when the first argument of the AND function evaluates to false, the overall value must be false; and when the first argument of the OR function evaluates to true, the overall value must be true.

It sees that the rest of the condition doesn't matter because one of the operands of || is already true (10 < 20). If one of the operands is true, then no matter what the rest of the condition is, it's true.

You may use bitwise & and | to prevent this.



But, the ( expr2 && expr3 ) should be evaluated before expr1, no ?

No. You have to separate concepts of precedence and evaluation order.

  • Precedence: Dictates the parenthesization of an expression, not the order in which an expression is evaluated. For an example:

      true || false && false

    Is parenthesized to this because && has higher precedence than ||:

      true || (false && false)

    This does not mean that things in parentheses is evaluated first in Java's case. Precedence just clarifies what the operands of an operator are, in this case false and false, where as in this case:

      (true || false) && (false || false)

    The operands for && are true and false, not false and false.

  • Evaluation Order: Describes in what order each operand is evaluated and operator is applied and is sometimes language specific. This dictates how an expression is evaluated, unlike precedence.

In this case, your example:

true || false && false

As established earlier, becomes this due to precedence:

true || (false && false)

But Java, unlike C++, JavaScript, or a number of other languages has a strictly left to right evaluation. Per the Java Language Specification:

15.7. Evaluation Order

The Java programming language guarantees that the operands of operators appear to be evaluated in a specific evaluation order, namely, from left to right.

15.7.1. Evaluate Left-Hand Operand First

The left-hand operand of a binary operator appears to be fully evaluated before any part of the right-hand operand is evaluated.

So, when you have:

true || (false && false)

Java first evaluates the left operand which turns out to be true. Then the whole condition short circuits. The right operand of || in the parentheses is never evaluated at all. The same goes for your other example:

a1 < a2 || (++a1 > a2 && ++a2 < a1)
^^^^^^^^^^^^^^^^^^^^^^^^
Step 0, precedence and parenthesization


a1 < a2 || (++a1 > a2 && ++a2 < a1)
^^^^^^^
Step 1, left operand evaluated, variables resolved to values 10 and 20, condition is true


true || (++a1 > a2 && ++a2 < a1)
^^^^
Step 2, short circuits, left operand is not evaluated

Take another more complex example:

false || false || true && (false || true) || false

Due to precedence, it becomes:

false || false || (true && (false || true)) || false

Then, evaluation begins, left to right:

false || false || (true && (false || true)) || false
^^^^^^^^^^^^^^
Step 1, false || false, does not short circuit, right operand is evaluated, is false


false || (true && (false || true)) || false
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Step 2, false || (true && (false || true)), does not short circuit, right operand is evaluated
Step 2A, (true && (false || true)), does not short circuit, right operand is evaluated
Step 2B, (false || true), does not short circuit, right operand is evaluated, is true
Step 2C, (true && true), does not short circuit, right operand is evaluated, is true
Step 2D, false || true, does not short circuit, right operand is evaluated, is true


true || false
^^^^
Step 3, true || false short circuits, right operand is not evaluated, is true

Thus the whole expression evaluates to true. The whole expression was evaluated left to right the whole way through. Precedence only dictated the operands of an operator via parenthesization, not the evaluation order.

Further reading at Eric Lippert's explanatory article on precedence vs associativity vs evaluation order as mentioned by Daniel Pryden, it clears up a lot of the confusion.

The main takeaway is that precedence does not dictate in what an expression is evaluated. It only dictates how an expression should be parenthesized. Evaluation order, on the other hand, tells us exactly how an expression is evaluated, and in Java's case is always left to right.

Logical OR and ternary operator evaluation order

Operator precedence is all about solving ambiguities. Let's say for example we have two operators op1 and op2 and the following expression:

x = a op1 b op2 c

We could resolve this logically as

tmp = a op1 b
x = tmp op2 c

But it would also be possible to evaluate op2 first, like so:

tmp = b op2 c
x = a op1 tmp

This is ambigous. To solve the ambiguity we could either demand parentheses or have to give one of the operators higher precedence. This is basically the same what we use in mathematics with an expression like 1 + 2 * 3 where the multiplication has higher precedence and has to be calculated first.

Wat does that mean for your example? As you've already written, || has a higher precedence than ?:. This means that

true || false

will be evaluated first and always results in true. So your ternary effectively becomes

true ? false : true

and will always result in false.

How does the compiler reach that decision? Let's have a (simplified) look at the steps:

  1. initially the compiler sees true which is already a value.
  2. the compiler sees || an knows now that there has to follow another value or evaluated expression.
  3. the compiler then sees false. This would be a value but since it could be part of another expression it's not done yet.
  4. next, the compiler encounters ? which it identifies this as the ternary operator
  5. since the ternary has a lower precedence than || it has to treat the entire expression true || false as the first operand of the ternary.

As to why the ternary operator has a lower precedence than || I can only speculate that it is for consistency. The ternary is not only the only operator with three operands but also only the second and the third need to have the same datatype whereas the first is always a bool. The lower precedence ensures that these two assignments are semantically the same:

bool b = condition1 || condition2 ? true : false;
int i = condition1 || condition2 ? 23 : 42;

Execution order of conditions in C# If statement

The && and || operators short-circuit. That is:

1) If && evaluates its first operand as false, it does not evaluate its second operand.

2) If || evaluates its first operand as true, it does not evaluate its second operand.

This lets you do null check && do something with object, as if it is not null the second operand is not evaluated.

What is the precedence of operators in C# Preprocessor Directives?

2.5.2 Pre-processing expressions

Evaluation of a pre-processing expression always yields a boolean
value. The rules of evaluation for a pre-processing expression are the
same as those for a constant expression (§7.19)
, except that the only
user-defined entities that can be referenced are conditional
compilation symbols

7.19 Constant expressions

The compile-time evaluation of constant expressions uses the same rules as run-time evaluation of non-constant expressions*, except that where run-time evaluation would have thrown an exception, compile-time evaluation causes a compile-time error to occur.

So the same operator precedence applies to pre-processing expressions, constant expressions and runtime evaluation.

7.3.1 Operator precedence and associativity

(...)

7.11 Logical AND &

7.11 Logical XOR ^

7.11 Logical OR |

7.12 Conditional AND &&

7.12 Conditional OR ||

(...)

From highest to lowest precedence.

Operator Logical-AND vs inline if else not compatible

This behaviour is correct. Let's see:

string s = "123";
Console.WriteLine(false && s.Length < 2 ? true : s.Substring(0,2).ToUpper() != "GA");

The expression for the ternary expression is:
false && s.Length < 2 // s.Length is 3 => 3 < 2 == false

Therefore the expression s.Substring(0,2).ToUpper() != "GA" is executed and returns true, as "12" != "GA".



Related Topics



Leave a reply



Submit