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 beforeEnumerableEqualByComparer.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 typebool
, or when the operands are of types that do not define an applicableoperator &
oroperator |
, but do define implicit conversions tobool
, the operation is processed as follows:[...]
The operation
x || y
is evaluated asx ? true : y
. In other words,x
is first evaluated and converted to typebool
. Then, ifx
is true, the result of the operation istrue
. Otherwise,y
is evaluated and converted to typebool
, 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 alreadytrue
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
andfalse
, where as in this case:(true || false) && (false || false)
The operands for
&&
aretrue
andfalse
, notfalse
andfalse
.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:
- initially the compiler sees
true
which is already a value. - the compiler sees
||
an knows now that there has to follow another value or evaluated expression. - the compiler then sees
false
. This would be a value but since it could be part of another expression it's not done yet. - next, the compiler encounters
?
which it identifies this as the ternary operator - since the ternary has a lower precedence than
||
it has to treat the entire expressiontrue || 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
Best Regular Expression for Email Validation in C#
Why Isn't Array a Generic Type
How to Get Duplicate Items from a List Using Linq
Should C# Methods That *Can* Be Static Be Static
Verifying Jwt Signed with the Rs256 Algorithm Using Public Key in C#
Best Way to Call a JSON Webservice from a .Net Console
Linq List of Lists to Single List
Setting/Getting the Class Properties by String Name
How to Populate a Dropdownlist from a Database
Creating Wcf Channelfactory<T>
Best Practice to Make a Multi Language Application in C#/Winforms
Client Side Groupby Is Not Supported
How to Use Microsoft.Office.Interop.Excel on a MAChine Without Installed Ms Office
Mixing C# & Vb in the Same Project
How to Find a Specific Element in a List<T>