Why combine operators
Real conditions often need more than one rule. A person gets in if they are a special student or their age falls between two limits, and "between" is itself two comparisons joined by and. In C#, you build such conditions by mixing && (and), || (or) and ! (not) in a single expression.
A quick reminder of the two main operators:
a && bis true only when both sides are true.a || bis true when at least one side is true.
Parentheses decide the grouping
Take the expression 7 >= 10 && (5 == 7 || 9 < 12). The parentheses group the two comparisons on the right, so the computer sees condition1 && condition2:
7 >= 10isfalse.(5 == 7 || 9 < 12)istrue, because9 < 12is true.
An && needs both sides true, and the left side is false, so the whole expression is false.
Move the parentheses and the meaning changes: (7 >= 10 && 5 == 7) || 9 < 12 is now condition1 || condition2. The left group is false and 9 < 12 is true, so the whole expression is true. The same four comparisons give opposite answers depending on the grouping.
Console.WriteLine(7 >= 10 && (5 == 7 || 9 < 12)); // False
Console.WriteLine((7 >= 10 && 5 == 7) || 9 < 12); // True
Precedence when you leave them out
C# has a fixed order of operations for logical operators. ! is applied first, then &&, then ||. So a || b && c is read as a || (b && c). Without parentheses, the second example above would mean the same as the one with the parentheses around 7 >= 10 && 5 == 7.
You don't have to memorise this. Adding parentheses costs nothing, and they tell the next reader exactly what you meant. Use them whenever && and || appear in the same condition.
Short-circuiting
Both && and || stop as soon as the answer is known. If the left side of && is false, the right side isn't evaluated. If the left side of || is true, the right side isn't evaluated either. This is why a check such as name != null && name.Length > 3 is safe: the length is only read when name isn't null.
Common mistakes
- Chained comparisons. The math notation
18 <= age <= 30doesn't work in C#. Write the two comparisons and join them:age >= 18 && age <= 30. - Using
||for a range.age >= 18 || age <= 30is true for every number. A range needs&&. - Off-by-one bounds. When the range includes both ends, use
>=and<=. With>and<, ages 18 and 30 would be excluded. - Relying on precedence alone. The code works, but a reader has to remember the rules. Parentheses make the intent visible.
- Mismatched parentheses. Every
(needs a). The outer parentheses of theifcount too, so a long condition can end in))or)) {.
The exercise, step by step
The code starts with bool specialStudent = false; and int age = 23;. The task is to let a person in when they are a special student or aged 18 to 30 inclusive, and to turn everyone else away.
- Write the age range. Both bounds are inclusive, so the range is
age >= 18 && age <= 30. Wrap it in parentheses. - Join it with the special-student check. Put
specialStudent ||in front, so the condition is true if the student is special or the age is in range. Print"Let him in!"when it holds. - Add the
else. Write} else {and print"Not allowed". It runs when both parts failed.
bool specialStudent = false;
int age = 23;
if (specialStudent || (age >= 18 && age <= 30)) {
Console.WriteLine("Let him in!");
} else {
Console.WriteLine("Not allowed");
}
The program evaluates the condition like this: specialStudent is false, so || moves on to the group. Then 23 >= 18 is true and 23 <= 30 is true, so the group is true. The output is:
Let him in!
Try age = 40 with specialStudent = false: the group is false and the output is Not allowed. With specialStudent = true, the output is Let him in! at any age.
Key takeaways
- Combine
&&,||and!to express conditions with several rules. - Parentheses control the grouping. The same comparisons can give different results under different grouping.
- Without parentheses,
!goes first, then&&, then||. - A range check joins two comparisons with
&&.