Team LiB
Previous Section Next Section

C# Expressions

A simple expression in C# is either

plus a few more expression types having to do with objects that you'll learn about in Chapter 13.

Assignment Statements

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

Arithmetic Operators

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.

Evaluating Expressions and Operator Precedence

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.

Logical Operators

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.


Team LiB
Previous Section Next Section