4.1. Boolean Expressions & Logical Operators#
4.1.1. Selection Statements#
Selection statements, sometimes referred to as conditional statements, are one of the three basic constructs (sequence, selection, iteration) in programming. Selection statements provide the logic to perform decision-making: taking different actions based on different conditions. When selecting from possible paths for execution, the decisions are made based on the value of an expression.
C# has the following conditional statements:
The
ifstatement specifies a block of code to be executed, only if a provided Boolean expression evaluates totrue.The
if-elsestatement allows you to choose which of the two code paths to follow based on a Boolean expression.The
else ifstatement specifies a newconditiontotest.switchstatement selects from a list of code to execute based on a pattern match with an expression.
The basic syntax for an if statement is:
if (condition)
{
// block of code to be executed if the condition is true
}
Here, condition is a Boolean expression — an expression that evaluates to either true or false. The parentheses around it are required syntax: they tell the compiler where the condition begins and ends, distinguishing it from the body of the if statement. This is different from parentheses in arithmetic expressions, where they are used to control the order of operations.
4.1.2. Boolean Data Type#
The condition in an if statement is a Boolean expression — also called a relational expression.
Every expression in C# produces a value, and the defining feature of a Boolean expression is that
its value is always either true or false (think: Yes/No, On/Off, 1/0).
This two-state result is represented by C#’s bool type, whose only legal values are true and false.
You can quickly try bool variables in csharprepl:
> bool isRollaQuiet = true;
> bool isChicagoClose = false;
> isRollaQuiet
true
> isChicagoClose
false
For a more complete example in VS Code, you can write a small program:
namespace Program
{
class Program
{
static void Main(string[] args)
{
BooleanExpression.Rolla();
}
}
internal class BooleanExpression
{
internal static void Rolla()
{
bool isRollaQuiet = true;
bool isChicagoClose = false;
Console.WriteLine(isRollaQuiet); // True
Console.WriteLine(isChicagoClose); // False
}
}
}
Note
BooleanExpression.Rolla() is called as a static method on a separate class.
This is a preview of how static methods in one class can be called from another —
a pattern covered in depth later in the course.
Output:
True
False
4.1.3. Boolean Expressions#
To drive decision-making in selection statements, Boolean expressions are typically
built using comparison operators (==, !=, <, >, <=, >=):
Operator |
Name |
Description |
|---|---|---|
|
Relational |
Compare numeric (and |
|
Equality |
|
|
Inequality |
Opposite of |
Examples:
Console.WriteLine(7.0 < 5.1); // False
Console.WriteLine(7.0 > 5.1); // True
Console.WriteLine(7.0 <= 5.1); // False
Console.WriteLine(7.0 >= 5.1); // True
int a = 1 + 2 + 3;
int b = 6;
Console.WriteLine(a == b); // True
char c1 = 'a';
char c2 = 'A';
Console.WriteLine(c1 == c2); // False (different character codes)
Reference types (classes) compare identity rather than value — two objects with identical contents are not equal unless they are the same instance. This is illustrated below.
public class ReferenceTypesEquality
{
public class MyClass
{
private int id;
public MyClass(int id) => this.id = id;
}
public static void Main()
{
var a = new MyClass(1);
var b = new MyClass(1);
var c = a;
Console.WriteLine(a == b); // output: False
Console.WriteLine(a == c); // output: True
}
}
Understanding boolean expressions above should give you a good sense of how
conditional/select statement syntax works:
if (condition)
{
// block of code to be executed if the condition is True
}
You should know that the condition is a Boolean expression, which will evaluate to either true or
false. The parentheses is a testing construct. If the testing construct results to
true, then the code block follows will be executed. Otherwise, the code block
follows will not be executed.
4.1.4. Compound Boolean Expressions#
4.1.5. Logical Operators#
To be eligible to graduate from M S&T, you must
have 120 credits and a GPA of at least 2.0. C# does not use the
word and. Instead it uses && (inherited from the C language).
Then, the requirement translates directly into C# as a compound condition
using the logical operator &&:
credits >= 120 && GPA >=2.0
This is true if both credits >= 120 is true and GPA >= 2.0
is true. A short example function using this would be:
static void checkGraduation(int credits, double GPA)
{
if (credits >= 120 && GPA >=2.0) {
Console.WriteLine("You are eligible to graduate!");
}
else {
Console.WriteLine("You are not eligible to graduate.");
}
}
The C# syntax for the logical operator && is:
condition1
&&condition2
The compound condition is true if both of the component conditions
are true. It is false if at least one of the conditions is false.
Suppose we want a C# condition that is true in the same situations
as the mathematical expression: low < val < high. Unfortunately the
math is not a C# expression. The C# operator < is binary.
In C#, the statement above is equivalent to
(low < val) < high
comparing a Boolean result to high, and causing a compiler error. There is a C# version. Be sure to use this pattern:
low < val && val < high
Now suppose we want the opposite condition: that val is not
strictly between low and high.
There are several approaches.
One is that val would be less than or equal to low
or greater than or equal to high. C# translate or into ||,
so a C# expression would be:
val <= low || val >= high
The C# syntax for the logical operator || is:
condition1
||condition2
The compound condition is true if at least one of the component conditions are true. It is false if both conditions are false.
Another logical way to express the opposite of the condition low < val < high
is that it is not the case
that low < val && val << high. C# translates not as !. Another way
to state the condition would be
!(low < val && val < high)
The parentheses are needed because the !
operator has higher precedence than
<.
A way to remember this strange not operator is to think of the use of !
in the not-equal operator: !=
The C# syntax for the operator !:
!condition
This whole expression is true when condition is false, and false when condition is true.
Because of the precedence of !, you are often going to write:
!(condition)
Remember when such a condition is used in an if statement, outer
parentheses are also needed:
if (!(condition)) {
Note that ! has the high precedence of unary arithmetic operators.
The operators && and || are almost at the bottom of the operators
considered in this book, just above the assignment operators, and below the
relational operators, with && above ||. You are encourages to use
parentheses to make sure.
Compound Overkill: Look back to the code converting a score to a letter grade in the LetterGrade2 (else-if Statements for Cases) method, the condition before assigning the B grade could have been:
(score >= 80 && score < 90)
That would have totally nailed the condition, but it is overly verbose in the
if .. else if … code where it appeared. Since you only get
to consider a B as a grade if the grade was not already
set to A, the second part of the compound condition above is redundant.
4.1.6. Compound test conditions#
Consider a different situation: Steven Covey suggested that people classify possible actions on two axes: urgent vs. not urgent and important vs. not important, leading to four possible combinations. We could ask a person to classify an activity this way, and them give a process comment, something like from Covey’s book:
Important and urgent: Be sure to schedule this promptly!
Important and not urgent: Make sure that this is included regularly in your plans! Do not let urgent but unimportant things interfere!
Not important and urgent: Can you skip this, or is it really worth letting this displace important things you need to do?
Not important and not urgent: Is there anything more worthwhile for you to do now?
Assume we have Boolean variables important and urgent.
There are four separate combinations, and we could handle this with a
chain of compound conditions checking for one at a time:
if (important && urgent) {
Console.WriteLine("Be sure ...");
}
else if (important && !urgent) {
Console.WriteLine("Make sure ...");
}
else if (!important && urgent) {
Console.WriteLine("Can you...");
}
else {
Console.WriteLine("Is there ...");
}
Compound test conditions are not necessary if we keep track of partial
answers by nesting if statements. Consider the two aspects separately
using an if-else statement with nested if-else sub-statements:
if (important) {
if (urgent) {
Console.WriteLine("Be sure ...");
}
else {
Console.WriteLine("Make sure ...");
}
}
else {
if (urgent) {
Console.WriteLine("Can you...");
}
else {
Console.WriteLine("Is there ...");
}
}
The outer if-else determines whether the action is important, so the inner
conditions only need to deal with urgency. Also note that in executing
this version there are never more than two short conditions evaluated.
In the first version, you may have to go through all three conditions.
Both approaches work. Which is clearer to you?
Footnotes