• No results found

Chapter 3: Writing C# Expressions

N/A
N/A
Protected

Academic year: 2021

Share "Chapter 3: Writing C# Expressions"

Copied!
19
0
0

Loading.... (view fulltext now)

Full text

(1)

Chapter 3: Writing C# Expressions

In This Chapter

z Unary Operators

z Binary Operators

z The Ternary Operator

z Other Operators z Enumeration Expressions z Array Expressions z Statements z Blocks z Labels z Declarations

z Operator Precedence and Associativity

C# provides a complete set of language elements for writing expressions. An expression is a set of language elements combined to perform a meaningful computation. This chapter provides guidance in building C# expressions.

This chapter demonstrates expressions created with each of C#’s built-in operators. All aspects of operators are covered in order to provide an understanding of their effects.

There are four types of operators—unary, binary, ternary, and a few others that don't fit into a category. Unary operators affect a single expression. Binary operators require two expressions to produce a result. The ternary operator has three expressions. The others can only be explained by reading each of their descriptions.

For C++ and Java Programmers

C# operators and their precedence are the same. No surprises here at all. If desired, you could skip this section without missing anything.

Unary Operators

As previously stated, unary operators affect a single expression. In many instances, the unary operators enable operations with simpler syntax than a comparable binary operation. The unary operators include

+ (plus), - (minus), ++ (increment), -- (decrement), ! (logical negation), and ~ (bitwise complement).

Note

Mathematical operations on floating-point types are performed according to IEEE 754 arithmetic.

(2)

The Plus Operator

The plus operator (+) has no effect on the expression it’s used with. Why would a language have an operator that has no effect? For consistency. Most C# operators have a logical complement. Since there is a minus operator, its logical complement is the plus operator. The + operator is available to explicitly document code. Here are a couple examples:

int negative = -1; int positive = 1; int result;

result = +negative; // result = -1 result = +positive; // result = 1

The Minus Operator

The minus operator (-) allows negation of a variable’s value. In integer and decimal types, the result is the number subtracted from zero. For floating-point types, the - operator inverts the sign of the number. When a value is NaN (not a number), the result is still NaN. Here are some examples:

int negInt = -1; decimal posDec = 1; float negFlt = -1.1f;

double nanDbl = Double.NaN; int resInt;

decimal resDec; float resFlt; double resDbl;

resInt = -negInt; // resInt = 1 resDec = -posDec; // resDec = -1 resFlt = -negFlt; // resFlt = 1.1 resDbl = -nanDbl; // resDbl = NaN

The Increment Operator

The increment operator (++) allows incrementing the value of a variable by 1. The timing of the effect of this operator depends upon which side of the expression it’s on.

Here’s a post-increment example:

int count; int index = 6;

count = index++; // count = 6, index = 7

In this example, the ++ operator comes after the expression index. That’s why it’s called a post-increment operator. The assignment takes place and then index is incremented. Since the assignment occurs first, the value of index is placed into count, making it equal 6. Then index is incremented to become 7.

(3)

Here’s an example of a pre-increment operator:

int count; int index = 6;

count = ++index; // count = 7, index = 7

This time the ++ operator comes before the expression index. This is why it’s called the pre-increment operator. Index is incremented before the assignment occurs. Since index is incremented first, its value becomes 7. Next, the assignment occurs to make the value of count equal 7.

The Decrement Operator

The decrement operator (--) allows decrementing the value of a variable. The timing of the effect of this operator again depends upon which side of the expression it is on. Here’s a post-decrement example:

int count; int index = 6;

count = index--; // count = 6, index = 5

In this example, the -- operator comes after the expression index, and that’s why it’s called a post-decrement operator. The assignment takes place and then index is decremented. Since the assignment occurs first, the value of index is placed into count, making it equal 6. Then index is decremented to become 5.

Here’s an example of a pre-decrement operator:

int count; int index = 6;

count = --index; // count = 5, index = 5

This time the -- operator comes before the expression index, which is why it’s called the pre-decrement operator. Index is decremented before the assignment occurs. Since index is decremented first, its value

becomes 5, and then the assignment occurs to make the value of count equal 5.

The Logical Complement Operator

A logical complement operator (!) serves to invert the result of a Boolean expression. The Boolean expression evaluating to true will be false. Likewise, the Boolean expression evaluating to false will

be true. Here are a couple examples:

bool bexpr = true;

bool bresult = !bexpr; // bresult = false bresult = !bresult; // bresult = true

The Bitwise Complement Operator

A bitwise complement operator (~) inverts the binary representation of an expression. All 1 bits are turned to 0. Likewise, all 0 bits are turned to 1. Here’s an example:

(4)

byte bitComp = 15; // bitComp = 15 = 00001111b

byte bresult = (byte) ~bitComp; // bresult = 240 = 11110000b

Binary Operators

Binary operators are those operators that work with two operands. For example, a common binary expression would be a + b—the addition operator (+) surrounded by two operands. The binary operators are further subdivided into arithmetic, relational, logical, and assignment operators.

Arithmetic Operators

This is the first group of binary operators, those supporting arithmetic expressions. Arithmetic

expressions are composed of two expressions with an arithmetic operator between them. This includes all the typical mathematical operators as expected in algebra.

The Multiplication Operator

The multiplication operator (*) evaluates two expressions and returns their product. Here's an example:

int expr1 = 3; int expr2 = 7; int product;

product = expr1 * expr2; // product = 21

The Division Operator

The division operator (/), as its name indicates, performs mathematical division. It takes a dividend expression and divides it by a divisor expression to produce a quotient. Here's an example:

int dividend = 45; int divisor = 5; int quotient;

quotient = dividend / divisor; // quotient = 9

Notice the use of integers in this expression. Had the result been a fractional number, it would have been truncated to produce the integer result.

The Remainder Operator

The remainder operator (%) returns the remainder of a division operation between a dividend and divisor. A common use of this operator is to create equations that produce a remainder that falls within a

specified range. Here's an example:

int dividend = 33; int divisor = 10; int remainder;

remainder = dividend % divisor; // remainder = 3

(5)

The Addition Operator

The addition operator (+) performs standard mathematical addition by adding one number to another. Here’s an example:

int one = 1; int two;

two = one + one; // two = 2

The Subtraction Operator

The subtraction operator (-) performs standard mathematical subtraction by subtracting the value of one expression from another. Here’s an example:

decimal debt = 537.50m; decimal payment = 250.00m; decimal balance;

balance = debt - payment; // balance = 287.50

The Left Shift Operator

To shift the bits of a number to the left, use the left shift operator (<<). The effect of this operation is that all bits move to the left a specified number of times. High-order bits are lost. Lower order bits are zero filled. This operator may be used on the int, uint, long, and ulong data types. Here’s an example.

uint intMax = 4294967295; // 11111111111111111111111111111111b uint byteMask;

byteMask = intMax << 8; // 11111111111111111111111100000000b

The Right Shift Operator

The right shift operator (>>) shifts the bits of a number to the right. By providing a number to operate on and the number of digits, every bit shifts to the right by the number of digits specified. Only use the right shift operator on int, uint, long, and ulong data types. The uint, ulong, positive int, and positive long types shift zeros from the left. The negative int and negative long types keep a 1 in the sign bit position and fill the next position to the right with a 0. Here are some examples:

uint intMax = 4294967295; // 11111111111111111111111111111111b uint shortMask; shortMask = intMax >> 16; // 00000000000000001111111111111111b int intMax = -1; // 11111111111111111111111111111111b int shortMask; shortMask = intMax >> 16; // 10000000000000001111111111111111b

For Java Programmers

(6)

Relational Operators

Relational operators are used to make a comparison between two expressions. The primary difference between relational operators and arithmetic operators is that relational operators return a bool type rather than a number. Another difference is that arithmetic operators are applicable to certain C# types whereas relational operators can be used on every possible C# type, whether built-in or not. Floating-point types are evaluated according to IEEE 754. The results of a relational expression are either true or false.

The Equal Operator

To see if two expressions are the same, use the equal operator (==). The equal operator works the same for integral, floating-point, decimal, and enum types. It simply compares the two expressions and returns a bool result. Here’s an example:

bool bresult;

decimal debit = 1500.00m; decimal credit = 1395.50m;

bresult = debit == credit; // bresult = false

When comparing floating-point types, +0.0 and –0.0 are considered equal. If either floating-point number is NaN (not a number), equal returns false.

The Not Equal Operator

The not equal operator (!=) is the opposite of the equal operator for all types, with a slight variation for floating-point types only. If one of the floating-point numbers is NAN (not a number), not equal returns true.

There are two forms of not equal applicable to expressions. The first is the normal not equal operator (! =). The other is a negation of the equal operator !(a==b). Normally, these two forms always evaluate to the same value. The exception occurs when evaluating floating-point expressions where one or both expressions evaluate to NaN and the relational operator in the negation of an expression is <, >, <=, or

>=. The a > b form evaluates to false, but the !(a<=b) evaluates to true. Here are some examples:

bool bresult;

decimal debit = 1500.00m; decimal credit = 1395.50m;

bresult = debit != credit; // bresult = true bresult = !(debit == credit); // bresult = true

The Less Than Operator

If it’s necessary to find out if one value is smaller than another, use the less than operator (<). The expression on the left is being evaluated and the expression on the right is the basis of comparison. When the expression on the left is a lower value than the expression on the right, the result is true. Otherwise, the result is false. Here’s an example:

(7)

short redBeads = 2; short whiteBeads = 23; bool bresult;

bresult = redBeads < whiteBeads; // bresult=true, work harder

The Greater Than Operator

If it’s necessary to know that a certain value is larger than another, use the greater than operator (>). It compares the expression on the left to the basis expression on the right. When the expression on the left is a higher value than the expression on the right, the result is true. Otherwise, the result is false. Here’s an example:

short redBeads = 13; short whiteBeads = 12; bool bresult;

bresult = redBeads > whiteBeads; // bresult=true, good job!

The Less Than or Equal Operator

Sometimes it’s necessary to know if a number is either lower than or equal to another number. That’s what the less than or equal operator (<=) is for. The expression on the left is compared to the expression on the right. When the expression on the left is either the same value as or less than the one on the right, less than or equal returns true. This operator is the opposite of the greater than operator, which means that !(a>b) would produce the same results. The exception is when there’s a floating-point expression evaluating to NaN, in which case the result is always true. Here’s an example of the less than or equal operator:

float limit = 4.0f;

float currValue = 3.86724f; bool Bresult;

bresult = currValue <= limit; // bresult = true

The Greater Than or Equal Operator

As its name implies, the greater than or equal operator (>=) checks a value to see if it’s greater than or equal to another. When the expression to the left of the operator is the same as or more than the expression on the right, greater than or equal returns true. The greater than or equal operator is the opposite of the less than operator. Here’s an example:

double rightAngle = 90.0d; double myAngle = 96.0d; bool isAbtuse;

isAbtuse = myAngle >= rightAngle; // Yes, myAngle is abtuse

Logical Operators

Logical operators perform Boolean logic on two expressions. There are three types of logical operators in C#: bitwise, Boolean, and conditional.

(8)

The bitwise logical operators perform Boolean logic on corresponding bits of two integral expressions. Valid integral types are the signed and unsigned int and long types. They return a compatible integral result with each bit conforming to the Boolean evaluation.

Boolean logical operators perform Boolean logic upon two Boolean expressions. The expression on the left is evaluated, and then the expression on the right is evaluated. Finally, the two expressions are evaluated together in the context of the Boolean logical operator between them. They return a bool result corresponding to the type of operator used.

The conditional logical operators operate much the same way as the Boolean logical operators with one exception in behavior: Once the first expression is evaluated and found to satisfy the results of the entire expression, the second expression is not evaluated. This is efficient because it doesn’t make sense to continue evaluating an expression when the result is already known.

The Bitwise AND Operator

The bitwise AND operator (&) compares corresponding bits of two integrals and returns a result with corresponding bits set to 1 when both integrals have 1 bits. When either or both integrals have a 0 bit, the corresponding result bit is 0. Here’s an example:

byte oddMask = 1; // 00000001b byte someByte = 85; // 01010101b bool isEven;

isEven = (oddMask & someByte) == 0; //(oddMask & someByte) = 1

The Bitwise Inclusive OR Operator

The bitwise inclusive OR operator (|) compares corresponding bits of two integrals and returns a result with corresponding bits set to 1 if either of the integrals have 1 bits in that position. When both integrals have a 0 in corresponding positions, the result is zero in that position. Here’s an example:

byte option1 = 1; // 00000001b byte option2 = 2; // 00000010b byte totalOptions;

totalOptions = (byte) (option1 | option2); // 00000011b

The Bitwise Exclusive OR Operator

The bitwise exclusive OR operator (^) compares corresponding bits of two integrals and returns a result with corresponding bits set to 1 if only one of the integrals has a 1 bit and the other integral has a 0 bit in that position. When both integral bits are 1 or when both are 0, the result’s corresponding bit is 0. Here’s an example:

byte invertMask = 255; // 11111111b byte someByte = 240; // 11110000b byte inverse;

inverse = (byte)(someByte ^ invertMask); //inversion=00001111b

(9)

The Boolean AND operator (&) evaluates two Boolean expressions and returns true when both expressions evaluate to true. Otherwise, the result is false. The result of each expression evaluated must return a bool result. Here’s an example:

bool inStock = false; decimal price = 18.95m; bool buy;

buy = inStock & (price < 20.00m); // buy = false

The Boolean Inclusive OR Operator

The Boolean inclusive OR operator (|) evaluates the results of two Boolean expressions and returns

true if either of the expressions returns true. When both expressions are false, the result of the Boolean inclusive OR evaluation is false. Both expressions evaluated must return a bool type value. Here’s an example:

int mileage = 2305; int months = 4; bool changeOil;

changeOil = mileage > 3000 | months > 3; // changeOil = true

The Boolean Exclusive OR Operator

The Boolean exclusive OR operator (^) evaluates the results of two Boolean expressions and returns

true if only one of the expressions returns true. When both expressions are true or both expressions

are false, the result of the Boolean exclusive OR expression is false. In other words, the expressions must be different. Here’s an example:

bool availFlag = false; bool toggle = true; bool available;

available = availFlag ^ toggle; // available = true

The Conditional AND Operator

The conditional AND operator (&&) is similar to the Boolean AND operator in that it evaluates two

expressions and returns true when both expressions are true. It is different when the first expression evaluates to false. Since both expressions must be true, it’s automatically assumed that if the first expression evaluates to false, the entire expression is false. Therefore, the conditional AND operator returns false and does not evaluate the second expression. When the first expression is true, the conditional AND operator goes ahead and evaluates the second expression. Here’s an example:

bool inStock = false; decimal price = 18.95m; bool buy;

buy = inStock && (price < 20.00m); // buy = false

(10)

The Conditional OR Operator

The conditional OR operator (||) is similar to the Boolean inclusive OR operator (|) in that it evaluates two expressions and returns true when either expression is true. The difference is when the first expression evaluates to true. Since either expression can be true to prove that the overall expression is

true, the operator automatically assumes that the entire expression is true when it finds the first expression is true. Therefore, the conditional OR operator returns true without evaluating the second expression. When the first expression is false, the conditional OR operator goes ahead and evaluates the second expression. Here’s an example:

int mileage = 4305; int months = 4; bool changeOil;

changeOil = mileage > 3000 || months > 3; // changeOil = true

Notice that because mileage > 3000 is true, months > 3 will never be evaluated.

Side Effects

Watch out for side effects with conditional Boolean operations. Side effects occur when your program depends on the expression on the right of the conditional logical operator being evaluated. If the expression on the right is not evaluated, this could cause a hard-to-find bug. The conditional logical operators are also called short circuit operators. Take a look at this example:

decimal totalSpending = 3692.48m; decimal avgSpending;

bool onBudget = totalSpending > 4000.00m && totalSpending < calcAvg();

Notice that the second half of the expression was not evaluated. If calcAvg() was supposed to change the value of a class field for later processing, there would be an error.

Warning

When using conditional AND and conditional OR operators, make sure a program does not depend upon evaluation of the right-hand side of the expression, because it may not be evaluated. Such side effects are likely to cause bugs.

Assignment Operators

This chapter has already demonstrated plenty of examples of the simple assignment operator in action. This section explains the compound operators and what can be expected from them. Basically, the concept is simple. A compound operator is a combination of the assignment operator and an arithmetic operator, bitwise logical operator, or Boolean logical operator. Here’s an example:

(11)

int total = 7;

total += 3; // total = 10

This is the same as saying: total = total + 3. Table 3.1 shows a list of the available compound assignment operators.

Table 3.1 Compound Assignment Operators

The Ternary Operator

The ternary operator contains three expressions, thus the name ternary. The first expression must be a Boolean expression. When the first expression evaluates to true, the value of the second expression is returned. When the first expression evaluates to false, the value of the third expression is returned. This is a concise and short method of making a decision and returning a choice based upon the result of the decision. The ternary operator is often called the conditional operator. Here’s an example:

long democratVotes = 1753829380624; long republicanVotes = 1753829380713;

string headline = democratVotes != republicanVotes ? "We Finally Have a Winner!" : recount();

Other Operators

C# has some operators that can’t be categorized as easily as the other types. These include the is, as,

sizeof(), typeof(), checked(), and unchecked() operators. The following sections explain each operator.

The is Operator

The is operator checks a variable to see if it’s a given type. If so, it returns true. Otherwise, it returns

false. Here’s an example.

Operator Function *= Multiplication /= Division %= Remainder += Addition -= Subtraction <<= Left Shift >>= Right Shift &= AND ^= Exclusive OR |= Inclusive OR

(12)

int i = 0;

bool isTest = i is int; // isTest = true

The as Operator

The as operator attempts to perform a conversion on a reference type. The following example tries to

convert the integer i into a string. If the conversion were successful, the object variable obj would hold a reference to a string object. When the conversion from an as operator fails, it assigns null to the

receiving reference. That’s the case in this example where obj becomes null because i is an integer, not a string:

int i = 0;

object obj = i as string;

Console.WriteLine("i {0} a string.",

obj == null ? "is not" : "is" ); // i is not a string.

The sizeof() Operator

C# provides a facility to perform low-level functions through a construct known as unsafe code. The

sizeof() operator works only in unsafe code. The operator takes a type and returns the type’s size in bytes. Here’s an example:

unsafe {

int intSize = sizeof(int); // intSize = 4 }

The typeof() Operator

The typeof() operator returns a Type object. The Type class holds type information about a value or reference type. The typeof() operator is used in various places in C# to discover information about reference and value types. The following example gets type information on the int type:

Type myType = typeof(int); Console.WriteLine(

"The int type: {0}", myType ); // The int type: Int32

The checked() Operator

The checked() operator detects overflow conditions in certain operations. The following example causes a system error by attempting to assign a value to a short variable that it can’t hold:

short val1 = 20000, val2 = 20000;

short myShort = checked((short)(val1 + val2)); // error

The unchecked() Operator

If it is necessary to ignore this error and accept the results regardless of overflow conditions, use the

unchecked() operator as in this example:

(13)

short myShort =

unchecked((short)(val1 + val2)); // error ignored

Tip

Use the /checked[+|-] command line option when the majority of program code should be checked (/checked+) or unchecked (/checked-). Then all that needs to be done inside the code is to annotate the exceptions with the checked() and unchecked() operators.

Enumeration Expressions

The elements of enumeration expressions evaluate the same as their underlying types. In addition to using normal operators, there are additional methods that can be performed with an enum type. An Enum

class is used to obtain the majority of functionality shown in this section. Where the Enum class is being used, the capitalized Enum class name prefixes the method call. The examples in this section refer to the following enum:

enum Weekday { Mon = 1, Tue, Wed, Thu, Fri, Sat = 10, Sun };

For C++ Programmers

C# enums have much more functionality than C++ enums.

As a typed value, the enum must be assigned to a variable of its type. For example, the underlying representation of a Weekday enum may default to an integral value, but it’s still a Weekday type. The following line shows the declaration and initialization of an enum variable:

Weekday w = Weekday.Mon;

During a Console.WriteLine() method call, enum values are printed with their names rather than their underlying integral values. Here’s an example:

Console.WriteLine("WeekDay: {0}", w); // WeekDay: Mon

The Format() method returns the string representation of an enum value, as shown here: Console.WriteLine("Format: {0}", w.Format()); // Format: Mon

To go in the opposite direction and convert a string to an enum, use the FromString() method. The arguments it accepts are the enum type, the string representation of the value to be converted, and a Boolean condition to verify case. The following example uses the typeof() operator to get the enum type. The string to be converted is Tue, and the method is case-sensitive.

(14)

Console.WriteLine("FromString: {0}",

Enum.FromString(typeof(EnumTest.Weekday), "Tue", true)); // FromString: Tue

To get the name of an enum variable, use the GetName() method. The following example shows the

GetName() method accepting the enum type and an instance of that enum type and returning its name as a string.

w = EnumTest.Weekday.Wed;

Console.WriteLine("GetName: {0}",

Enum.GetName(typeof(EnumTest.Weekday), w)); // GetName: Wed

If there is a need to get the string representations of all the members of an enum, use the GetNames()

method—plural of the previous method. The following example shows an array being filled with the names. The method call only needs the enum type.

string[] weekDays = new string[7];

weekDays = Enum.GetNames(typeof(EnumTest.Weekday));

Console.WriteLine("Day 1: {0}", weekDays[0]); // Day 1: Mon Console.WriteLine("Day 2: {0}", weekDays[1]); // Day 2: Tue Console.WriteLine("Day 3: {0}", weekDays[2]); // Day 3: Wed Console.WriteLine("Day 4: {0}", weekDays[3]); // Day 4: Thu Console.WriteLine("Day 5: {0}", weekDays[4]); // Day 5: Fri Console.WriteLine("Day 6: {0}", weekDays[5]); // Day 6: Sat Console.WriteLine("Day 7: {0}", weekDays[6]); // Day 7: Sun

A corresponding method to get the values of an enum is the GetValues() method. The following example shows the GetValues() method accepting an enum type and returning an array of objects. Notice that the array is of type objects. In C#, all types are also object types. Therefore, any type can be assigned to the object type.

object[] weekDayVals = new object[7];

weekDayVals = Enum.GetValues(typeof(EnumTest.Weekday));

Console.WriteLine("Day 1: {0}", weekDayVals[0]); // Day 1: Mon Console.WriteLine("Day 2: {0}", weekDayVals[1]); // Day 2: Tue Console.WriteLine("Day 3: {0}", weekDayVals[2]); // Day 3: Wed Console.WriteLine("Day 4: {0}", weekDayVals[3]); // Day 4: Thu Console.WriteLine("Day 5: {0}", weekDayVals[4]); // Day 5: Fri Console.WriteLine("Day 6: {0}", weekDayVals[5]); // Day 6: Sat Console.WriteLine("Day 7: {0}", weekDayVals[6]); // Day 7: Sun

To find out the underlying type of an enum, use the GetUnderlyingType() method. It accepts an enum type argument, and the return value is the integral type of the enum's underlying type. Here's an

example:

Console.WriteLine("Underlying Type: {0}", Enum.GetUnderlyingType(

typeof(EnumTest.Weekday))); // Underlying Type: Int32

When it's necessary to determine if an enum value is defined, use the IsDefined() method. It accepts an enum type and an enum value and returns a Boolean true if the value is defined in the enum.

(15)

w = EnumTest.Weekday.Thu;

Console.WriteLine("Thu is Defined: {0}",

Enum.IsDefined(typeof(EnumTest.Weekday), w)); // Thu is Defined: True

To obtain an enum type that is set to a specific value, use the ToObject() method. The following

example shows the method accepting an enum type and an integer, and returning an enum of the requested type with the value corresponding to the integer.

Console.WriteLine("Get Friday: {0}",

Enum.ToObject(typeof(EnumTest.Weekday), 5)); // Get Friday: Fri

Array Expressions

Besides being an efficient storage construct, arrays have additional functionality that helps make programs more expressive and powerful. The following example shows one such capability:

string[] weekDays = new string[7];

Console.WriteLine("Number of Days: {0}", weekDays.Length); // Number of Days: 7

For C++ Programmers

From the perspective of traditional built-into-the-language arrays, C++ arrays are simply a pointer to a block of memory. This refers to the C++ arrays derived from its C language ancestry. C# arrays have much more functionality.

The C++ STL array class is similar to the C# ArrayList collection class. Both are library classes.

The previous example showed the array’s Length property. The array type has many more methods and properties, as shown in Table 3.2.

Table 3.2 C# Array Members

Method/Property Description

AsList Returns an Ilist representation of the array BinarySearch Finds a value in a one-dimensional array

using a binary search

Clear Cleans out a range of array values by setting

them to 0 or null

Copy Copies a range of array elements to another

(16)

Statements

Statements in C# are single entities that cause a change in the program’s current state. They’re commonly associated with some type of assignment statement, changing the value of a variable. A statement ends with a semicolon (;). Leave one out and the compiler will issue a prompt notification. Statements may span multiple lines, which could help make your code more readable, as the following example shows:

decimal closingCosts = loanOrigination + appraisal

+ titleSearch

CreateInstance Creates a new instance of an array IndexOf Finds the first occurrence of a value and

returns its index

LastIndexOf Finds the last occurrence of a value and

returns its index

Reverse Reverses the elements of a one-dimensional

array

Sort Sorts a one-dimensional array IsReadOnly Returns true if read-only IsSynchronized Returns true if synchronized

Length Returns the number of elements in all

dimensions

Rank Returns the number of dimensions SyncRoot Returns array synchronization object Clone Performs a shallow copy

CopyTo Copies from one array to another Equals Compares array references for equality GetEnumerator Returns an IEnumerator of a

one-dimensional array

GetHashCode Returns a unique identifier

GetLength Returns the number of elements in specified

dimension

GetLowerBound Returns the lower bound of a dimension GetType Returns the Type object

GetUpperBound Returns the upper bound of a dimension GetValue Returns values from specified elements Initialize Calls the default constructor of each element SetValue Sets values of specified elements

(17)

+ insuranceAdvance + taxAdvance

+ points

+ realtorCommission

+ whateverElseTheyCanRipYouOffFor;

Had the statement been placed on one line, it would have either continued off the right side of the page or wrapped around in an inconvenient location. This way, each item is visible, lined up nicely, and easier to understand.

Blocks

Setting off code in blocks clearly delimits the beginning and ending of a unit of work and establishes scope. Begin a block of code with a left-hand brace ({), and end it with a right-hand brace (}). Blocks are required to specify the boundaries of many language elements such as classes, interfaces, structures, properties, indexers, events, and methods.

Labels

Labels are program elements that simply identify a location in a program. Their only practical use is to support the goto statement. The goto statement allows program control to jump to the place where a label is defined. A label is any valid identifier followed by a colon (not a semicolon). Here are two examples:

loop: // a label named "loop"

jumphere: // a label named "jumphere"

Declarations

Declarations enable definition and announcement of the existence and nature of program data. There are two forms of declaration in C#: simple declaration and declaration with initialization. A simple

declaration takes the following form:

<type> <identifier>;

The type may be any C# or user-defined type. The identifier is any valid identifier as defined in Chapter 2, "Getting Started with C#."

A declaration with initialization looks like this:

<type> <identifier> = <expression>;

The type and identifier are the same as the previous example. The equal sign takes the evaluated expression on its right and loads it into the variable declared on the left. The expression can be any valid C# statement evaluating to the type of variable specified by type. The declaration is a statement

followed by a semicolon.

(18)

When evaluating C# expressions, there are certain rules to ensure the outcome of the evaluation. These rules are governed by precedence and associativity and preserve the semantics of all C# expressions. Precedence refers to the order in which operations should be evaluated. Sub-expressions with higher operator precedence are evaluated first.

There are two types of associativity: left and right. Operators with left associativity are evaluated from left to right. When an operator has right associativity, its expression is evaluated from right to left. For example, the assignment operator is right associative. Therefore, the expression to its right is evaluated before the assignment operation is invoked. Table 3.3 shows the C# operators, their precedence, and associativity.

Certain operators have precedence over others to guarantee the certainty and integrity of computations. One effective rule of thumb when using most operators is to remember their algebraic precedence. Here’s an example:

int result;

result = 5 + 3 * 9; // result = 32

This computes 3 * 9 = 27 + 5 = 32. To alter the order of operations use parentheses, which have a higher precedence:

result = (5 + 3) * 9; // result = 72

This time, 5 and 3 were added to get 8 and then multiplied by 9 to get 72. See Table 3.3 for a listing of operator precedence and associativity. Operators in top rows have precedence over operators in lower rows. Operators on the left in each row have higher precedence over operators to the right in the same row.

Table 3.3 Operator Precedence and Associativity

Operators Associativity

(x), x.y, f(x), a[x], x++, x--, new,

Left

typeof, sizeof, checked,

unchecked

+ (unary), – (unary), ~, ++x, --x, (T)x

Left

*, / % Left

+ (arithmetic), – (arithmetic) Left

<<, >> Left <, >, <=, >=, is, as Left ==, != Left & Left ^ Left | Left

(19)

Summary

This chapter covered the various C# operators—unary, arithmetic, relational operators, and other operators—and provided examples of how to use them.

The unary operators include plus, minus, increment, decrement, logical complement, and bitwise complement operators. Binary operators include the arithmetic, logical, relational and assignment operators. There is a single ternary operator that produces conditional results. C# has a few other operators that don't fit into the any of those categories; they include the is, as, typeof, sizeof,

checked, and unchecked operators.

The enum and array types have additional functions that make programs more expressive and powerful. I included several examples of enums and a table of array methods and properties.

This chapter also described statements, blocks, labels, and declarations, and included a section about operator precedence and associativity.

Having mastered the material in this chapter, it's simple to move into logical manipulation of program flow.

© Copyright Pearson Education. All rights reserved.

&& Left || Left ?: Right =, *=, /=, %=, +=, -=, <<=, >>=, &=, ^=, |= Right

References

Related documents

Favor you leave and sample policy employees use their job application for absence may take family and produce emails waste company it discusses email etiquette Deviation from

support they required or provided to enable the athlete to maintain their dual

—   The results of this analysis highlighted the need for a rehabilitation technology that provides structural integrity independent of the existing host pipe... —  

Senator Young felt the language used would make it mandatory rather than optional and Senator Swobe said this was not the intent, however he would check with

4) An object will sink in water if its density is greater than the density of water. As the volume of the box increases, the pressure increases

David (1999) was amazed at the change in roles she experienced when she switched from her role as a reading specialist to that of a literacy coach. For the past 15 years, I have

As long as the table space is in backup mode Oracle will write the entire block is dumped to redo when the ALTER TABLESPACE TBSNAME BEGIN BACKUP MODE is entered but later

CASE statement evaluates a explain of Boolean expressions and, scramble it finds an advance that evaluates to TRUE, executes a clap of statements associated with certain