Boolean Expressions
The parenthesized condition of the if statement is a Boolean expression. In Listing 3.28, the condition is highlighted.
Listing 3.28. Boolean Expression
if
(input < 9
) { // Input is less than 9. System.Console.WriteLine("Tic-tac-toe has more than {0}"
+" maximum turns."
, input); } // ...
Boolean expressions appear within many control flow statements. Their key characteristic is that they always evaluate to true or false. For input<9 to be allowed as a Boolean expression, it must result in a bool. The compiler disallows x=42, for example, because it assigns x and results in the value that was assigned, instead of checking whether the value of the variable is 42.
Relational and Equality Operators
Relational and equality operators determine whether a value is greater than, less than, or equal to another value. Table 3.2 lists all the relational and equality operators. All are binary operators.
Table 3.2. Relational and Equality Operators
Operator |
Description |
Example |
< |
Less than |
input<9; |
> |
Greater than |
input>9; |
<= |
Less than or equal to |
input<=9; |
>= |
Greater than or equal to |
input>=9; |
== |
Equality operator |
input==9; |
!= |
Inequality operator |
input!=9; |
The C# syntax for equality uses ==, just as many other programming languages do. For example, to determine whether input equals 9 you use input==9. The equality operator uses two equal signs to distinguish it from the assignment operator, =. The exclamation point signifies NOT in C#, so to test for inequality you use the inequality operator, !=.
Relational and equality operators always produce a bool value, as shown in Listing 3.30.
Listing 3.30. Assigning the Result of a Relational Operator to a bool Variable
bool
result = 70 > 7;
In the tic-tac-toe program (see Appendix B), you use the equality operator to determine whether a user has quit. The Boolean expression of Listing 3.31 includes an OR (||) logical operator, which the next section discusses in detail.
Listing 3.31. Using the Equality Operator in a Boolean Expression
if
(input ==""
|| input =="quit"
) { System.Console.WriteLine("Player {0} quit!!"
, currentPlayer);break
; }
Logical Boolean Operators
The logical operators have Boolean operands and produce a Boolean result. Logical operators allow you to combine multiple Boolean expressions to form more complex Boolean expressions. The logical operators are |, ||, &, &&, and ^, corresponding to OR, AND, and exclusive OR. The | and & versions of OR and AND are only rarely used for Boolean logic, for reasons which we discuss below.
OR Operator (||)
In Listing 3.31, if the user enters quit or presses the Enter key without typing in a value, it is assumed that she wants to exit the program. To enable two ways for the user to resign, you use the logical OR operator, ||.
The || operator evaluates Boolean expressions and results in a true value if either operand is true (see Listing 3.32).
Listing 3.32. Using the OR Operator
if
((hourOfTheDay > 23) || (hourOfTheDay < 0)) System.Console.WriteLine("The time you entered is invalid."
);
It is not necessary to evaluate both sides of an OR expression because if either operand is true, the result is known to be true regardless of the value of the other operand. Like all operators in C#, the left operand is evaluated before the right one, so if the left portion of the expression evaluates to true, the right portion is ignored. In the example above, if hourOfTheDay has the value 33, (hourOfTheDay > 23) will evaluate to true and the OR operator will ignore the second half of the expression, short-circuiting it. Short-circuiting an expression also occurs with the Boolean AND operator. (Note that the parentheses are not necessary here; the logical operators are of higher precedence than the relational operators. However, it is clearer to the novice reader to parenthesize the subexpressions for clarity.)
AND Operator (&&)
The Boolean AND operator, &&, evaluates to true only if both operands evaluate to true. If either operand is false, the result will be false. Listing 3.33 writes a message if the given variable is both greater than 10 and less than 24.4 Similarly to the OR operator, the AND operator will not always evaluate the right side of the expression. If the left operand is determined to be false, the overall result will be false regardless of the value of the right operand, so the runtime skips evaluating the right operand.
Listing 3.33. Using the AND Operator
if
((10 < hourOfTheDay) && (hourOfTheDay < 24)) System.Console.WriteLine("Hi-Ho, Hi-Ho, it's off to work we go."
);
Exclusive OR Operator (^)
The caret symbol, ^, is the “exclusive OR” (XOR) operator. When applied to two Boolean operands, the XOR operator returns true only if exactly one of the operands is true, as shown in Table 3.3.
Table 3.3. Conditional Values for the XOR Operator
Left Operand |
Right Operand |
Result |
True |
True |
False |
True |
False |
True |
False |
True |
True |
False |
False |
False |
Unlike the Boolean AND and Boolean OR operators, the Boolean XOR operator does not short-circuit: It always checks both operands, because the result cannot be determined unless the values of both operands are known. Note that the XOR operator is exactly the same as the Boolean inequality operator.
Logical Negation Operator (!)
The logical negation operator, or NOT operator, !, inverts a bool value. This operator is a unary operator, meaning it requires only one operand. Listing 3.34 demonstrates how it works, and Output 3.16 shows the results.
Listing 3.34. Using the Logical Negation Operator
bool
valid =false
;bool result = !valid;
// Displays "result = True". System.Console.WriteLine("result = {0}"
, result);
Output 3.16.
result = True
To begin, valid is set to false. You then use the negation operator on valid and assign the value to result.
Conditional Operator (?:)
In place of an if-else statement used to select one of two values, you can use the conditional operator. The conditional operator uses both a question mark and a colon; the general format is as follows:
condition ? consequence : alternative
The conditional operator is a “ternary” operator because it has three operands: condition, consequence, and alternative. (As it is the only ternary operator in C#, it is often called “the ternary operator,” but it is clearer to refer to it by its name than by the number of operands it takes.) Like the logical operators, the conditional operator uses a form of short-circuiting. If the condition evaluates to true, the conditional operator evaluates only consequence. If the conditional evaluates to false, it evaluates only alternative. The result of the operator is the evaluated expression.
Listing 3.35 is an example of how to use the conditional operator. The full listing of this program appears in Appendix B.
Listing 3.35. Conditional Operator
public class
TicTacToe {public static string
Main() { // Initially set the currentPlayer to Player 1;int
currentPlayer = 1; // ...for
(int
turn = 1; turn <= 10; turn++) { // ... // Switch playerscurrentPlayer = (currentPlayer == 2) ? 1 : 2;
} } }
The program swaps the current player. To do this, it checks whether the current value is 2. This is the conditional portion of the conditional expression. If the result of the condition is true, the conditional operator results in the “consequence” value 1. Otherwise, it results in the “alternative” value 2. Unlike an if statement, the result of the conditional operator must be assigned (or passed as a parameter). It cannot appear as an entire statement on its own.
The C# language requires that the consequence and alternative expressions in a conditional operator be consistently typed, and that the consistent type be determined without examination of the surrounding context of the expression. For example, f ? "abc" : 123 is not a legal conditional expression because the consequence and alternative are a string and a number, neither of which is convertible to the other. Even if you say object result = f ? "abc" : 123; the C# compiler will still flag this expression as illegal because the type that is consistent with both expressions (that is, object) is found outside the conditional expression.
Null Coalescing Operator (??)
The null coalescing operator is a concise way to express “if this value is null then use this other value.” Its form is:
expression1 ?? expression2;
The null coalescing operator also uses a form of short-circuiting. If expression1 is not null, its value is the result of the operation and the other expression is not evaluated. If expression1 does evaluate to null, the value of expression2 is the result of the operator. Unlike the conditional operator, the null coalescing operator is a binary operator.
Listing 3.36 is an example of how to use the null coalescing operator.
Listing 3.36. Null Coalescing Operator
string
fileName = GetFileName(); // ...string fullName = fileName ?? "default.txt";
// ...
In this listing, we use the null coalescing operator to set fullName to "default.txt" if fileName is null. If fileName is not null, fullName is simply assigned the value of fileName.
The coalescing operator “chains” nicely; an expression of the form x ?? y ?? z results in x if x is not null; otherwise, it results in y if y is not null; otherwise, it results in z. That is, it goes from left to right and picks out the first non-null expression, or uses the last expression if all the previous expressions were null.
The null coalescing operator was added to C# in version 2.0 along with nullable value types; the null coalescing operator works on both operands of nullable value types and reference types.