A simple expression in C# is either
A constant: 7, false
A char(acter) literal: ‘A’, ‘&’
A string literal: "foo"
The name of any variable declared to be of one of the predefined types that we've discussed so far: myString, x
Any two of the preceding items that are combined with one of the C# binary operators (discussed in detail later in this chapter): x + 2
Any one of the preceding items that is modified by one of the C# unary operators (discussed in detail later in this chapter): i++
Any of the preceding simple expressions enclosed in parentheses: (x + 2)
plus a few more expression types having to do with objects that you'll learn about in Chapter 13.
Assigning a value to a variable is accomplished by using the assignment operator, =. An assignment statement consists of a (previously declared) variable name to the left of the =, and an expression that evaluates to the appropriate type to the right of the =. For example:
int count = 1; total = total + 4.0; // assuming that total was declared to be a double variable price = cost + (a + b)/length; // assuming all variables properly declared
The C# language provides a number of basic arithmetic operators, as follows:
+ |
Addition |
− |
Subtraction |
* |
Multiplication |
/ |
Division |
% |
Modulus (The modulus is the remainder when the operand to the left of the % operator is divided by the operand to the right.) |
The + and − operators can also be used in prefix fashion to indicate positive or negative numbers: −3.7, +42.
In addition to the simple assignment operator, =, there are a number of specialized compound assignment operators, which combine variable assignment with an operation. The compound assignment operators for arithmetic operations are as follows:
+= |
a += b is equivalent to a = a + b. |
−= |
a −= b is equivalent to a = a − b. |
*= |
a *= b is equivalent to a = a * b. |
/= |
a /= b is equivalent to a = a / b. |
%= |
a %= b is equivalent to a = a % b. |
Note?/td> |
The compound assignment operators don't add any new functionality; they are simply provided as a convenience to simplify code. For example, the statement total = total + 4.0; can be alternatively written as total += 4.0; |
The final two arithmetic operators that we'll introduce are the increment (++) and decrement (−−) operators, which are used to increase or decrease the value of an integer variable by 1 or of a floating point value by 1.0. The increment and decrement operators can also be used on char variables. For example, consider the following code snippet:
char c = 'e'; c++;
When the code snippet is executed, the variable c will have the value f, which is the next character in the Unicode sorting sequence.
The increment and decrement operators can be used in either a prefix or postfix manner.
If the operator is placed before the variable it's operating on (prefix mode), the increment or decrement of that variable is performed before the variable's value is used in any assignments made via that statement.
If the operator is placed after the variable it's operating on (postfix mode), the increment or decrement occurs after the variable's value is used in any assignments made via that statement.
For example, consider the following code snippet, which uses the prefix increment (++) operator:
int a = 1; int b = ++a; // a will be incremented to 2, then b will be assigned the value 2
After both lines of code have executed, the value of variable a will be 2, as will the value of variable b. This is because, in the second line of code, the increment of variable a (from 1 to 2) occurs before the value of a is assigned to variable b. The preceding two lines of code are logically equivalent to the following three lines:
int a = 1; a = a + 1; int b = a;
Now let's look at the same code snippet with the increment operator written in a postfix manner:
int a = 1; int b = a++; // b will be assigned the value 1, then a will be incremented to 2
After both lines of code have executed, the value of variable b will be 1, whereas the value of variable a will be 2. This is because, in the second line of code, the increment of variable a (from 1 to 2) occurs after the (old) value of a is assigned to variable b. The preceding two lines of code are logically equivalent to the following three lines:
int a = 1; int b = a; a = a + 1;
Here is a slightly more complex example:
int y = 1; int z = 2; int x = y++ * ++z; // x will be assigned the value 3, because z will be // incremented from 2 to 3 before its value is used in the // multiplication, whereas y will remain at 1 until AFTER its // value is used.
As you'll see in a bit, the increment and decrement operators are commonly used in loops and other flow of control structures.
Expressions of arbitrary complexity can be built up around the various simple expression types by nesting parentheses—e.g., ((((4/x) + y) * 7) + z). The compiler evaluates such expressions from innermost to outermost parentheses, left to right. Assuming that x, y, and z are declared and initialized as shown here:
int x = 1; int y = 2; int z = 3;
then the expression on the right-hand side of the following assignment statement:
int answer = ((8 * (y + z)) + y) * x;
would be evaluated piece by piece as follows:
((8 * (y + z)) + y) * x ((8 * 5) + y) * x (40 + y) * x 42 * x 42
In the absence of parentheses, certain operators take precedence over others in terms of when they will be applied in evaluating an expression. For example, multiplication or division is by default performed before addition or subtraction. The automatic precedence of one operator over another can be explicitly altered through the use of parentheses; operations inside parentheses will be performed before operations outside of them. Consider the following code snippet:
int j = 2 + 3 * 4; // j will be assigned the value 14 int k = (2 + 3) * 4; // k will be assigned the value 20
In the first line of code, which uses no parentheses, the multiplication operation takes precedence over the addition operation, and so the overall expression evaluates to the value 2 + 12 = 14; it's as if we've explicitly written "2 + (3 * 4)" without having to do so.
In the second line of code, parentheses are explicitly placed around the operation "2 + 3" so that the addition operation will be performed first, and the resultant sum will then be multiplied by 4 for an overall expression value of 5 * 4 = 20.
A logical expression compares two (simple or complex) expressions exp1 and exp2, in a specified way, and evaluates to a Boolean value of true or false.
To create logical expressions, C# provides the following relational operators:
exp1 == exp2 |
true if exp1 equals exp2 (note use of a double equal sign). |
exp1 > exp2 |
true if exp1 is greater than exp2. |
exp1 >= exp2 |
true if exp1 is greater or equal to exp2. |
exp1 < exp2 |
true if exp1 is less than exp2. |
exp1 <= exp2 |
true if exp1 is less than or equal to exp2. |
exp1 != exp2 |
true if exp1 isn't equal to exp2 (! is read as "not"). |
!exp |
true if exp is false, and false if exp is true. |
In addition to the relational operators, C# provides logical operators that can be used in combination with the relational operators to create complex logical expressions that involve more than one comparison.
&& |
Logical "and" |
|| |
Logical "or" |
! |
Logical "not" (The ! operator toggles the value of a logical expression from true to false and vice versa.) |
The logical "and" and "or" operators are binary operators; their left and right operands must both be valid logical expressions so that they evaluate to Boolean values. If the && operator is used, both the left and right operands must be true for the compound logical expression to be true. With the || operator, the compound logical expression will be true if either the left or right operand is true.
Here is an example that uses the logical "and" operator to program the compound logical expression "if x is greater than 2.0 and y isn't equal to 4.0":
if (x > 2.0 && y != 4.0) { // Pseudocode. do some stuff ... }
Note that, because the > and != operators take precedence over the && operator, we don't need to insert extra parentheses as shown here:
if ((x > 2.0) && (y != 4.0)) { // Pseudocode. do some stuff ... }
but may wish to do so to enhance readability.
Logical expressions are most commonly seen in flow of control structures, discussed later in this chapter.