Writing C# Expressions
Source: C# Unleashed
Chapter 3: Writing C#Expressions
In This Chapter
- Unary Operators
- Binary Operators
- The Ternary Operator
- Other Operators
- Enumeration Expressions
- Array Expressions
- Statements
- Blocks
- Labels
- Declarations
- 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 meaningfulcomputation. This chapter provides guidance in building C# expressions.
This chapter demonstrates expressions created with each of C#'s built-inoperators. All aspects of operators are covered in order to provide anunderstanding of their effects.
There are four types of operators—unary, binary, ternary, and a fewothers that don't fit into a category. Unary operators affect a singleexpression. Binary operators require two expressions to produce a result. Theternary operator has three expressions. The others can only be explained byreading each of their descriptions.
For C++ and Java Programmers
C#operators and their precedence are the same. No surprises here at all. Ifdesired, you could skip this section without missing anything.
Unary Operators
As previously stated, unary operators affect a single expression. In manyinstances, the unary operators enable operations with simpler syntax than acomparable binary operation. The unary operators include + (plus),- (minus), ++ (increment), -- (decrement), !(logical negation), and ~ (bitwise complement).
Note
Mathematical operations onfloating-point types are performed according to IEEE 754 arithmetic.
The Plus Operator
The plus operator (+) has no effect on the expression it's usedwith. 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 isavailable 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. Forfloating-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 avariable by 1. The timing of the effect of this operator depends upon which sideof 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 expressionindex. That's why it's called a post-increment operator. Theassignment takes place and then index is incremented. Since theassignment occurs first, the value of index is placed intocount, making it equal 6. Then index is incremented to become7.
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 expressionindex. This is why it's called the pre-increment operator.Index is incremented before the assignment occurs. Since indexis incremented first, its value becomes 7. Next, the assignment occurs to makethe value of count equal 7.
The Decrement Operator
The decrement operator (--) allows decrementing the value of avariable. The timing of the effect of this operator again depends upon whichside 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 expressionindex, and that's why it's called a post-decrement operator.The assignment takes place and then index is decremented. Since theassignment occurs first, the value of index is placed intocount, making it equal 6. Then index is decremented to become5.
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 expressionindex, which is why it's called the pre-decrement operator.Index is decremented before the assignment occurs. Since indexis decremented first, its value becomes 5, and then the assignment occurs tomake the value of count equal 5.
The Logical Complement Operator
A logical complement operator (!) serves to invert the result of aBoolean expression. The Boolean expression evaluating to true will befalse. Likewise, the Boolean expression evaluating to falsewill 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 representationof an expression. All 1 bits are turned to 0. Likewise, all
0 bits are turned to1. Here's an example:
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. Forexample, a common binary expression would be a + b—the additionoperator (+) surrounded by two operands. The binary operators arefurther subdivided into arithmetic, relational, logical, and assignmentoperators.
Arithmetic Operators
This is the first group of binary operators, those supporting arithmeticexpressions. Arithmetic expressions are composed of two expressions with anarithmetic operator between them. This includes all the typical mathematicaloperators as expected in algebra.
The Multiplication Operator
The multiplication operator (*) evaluates two expressions andreturns 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, performsmathematical division. It takes a dividend expression and divides it by adivisor 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 afractional number, it would have been truncated to produce the integerresult.
The Remainder Operator
The remainder operator (%) returns the remainder of a divisionoperation between a dividend and divisor. A common use of this operator is tocreate 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
No matter what, as long as the divisor stays at 10, the remainder will alwaysbe between 0 and 9.
The Addition Operator
The addition operator (+) performs standard mathematical addition byadding 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 mathematicalsubtraction by subtracting the value of one expression from another. Here'san 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 theleft a specified number of times. High-order bits are lost. Lower order bits arezero filled. This operator may be used on the int, uint, long, and ulong datatypes. 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 tothe right. By providing a number to operate on and the number of digits, everybit shifts to the right by the number of digits specified. Only use the rightshift operator on int, uint, long, and ulongdata types. The uint, ulong, positive int, andpositive long types shift zeros from the left. The negativeint and negative long types keep a 1 in the sign bitposition and fill the next position to the right with a 0. Here aresome examples:
uint intMax = 4294967295; // 11111111111111111111111111111111b
uint shortMask;
shortMask = intMax >> 16; // 00000000000000001111111111111111b
int intMax = -1; // 11111111111111111111111111111111b
int shortMask;
shortMask = intMax >> 16; // 10000000000000001111111111111111b
For Java Programmers
C# doesn'thave a right shift with zero extension operator (>>>).
Relational Operators
Relational operators are used to make a comparison between two expressions.The primary difference between relational operators and arithmetic operators isthat relational operators return a bool type rather than a number. Anotherdifference is that arithmetic operators are applicable to certain C# typeswhereas relational operators can be used on every possible C# type, whetherbuilt-in or not. Floating-point types are evaluated according to IEEE 754. Theresults of a relational expression are either true orfalse.
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, andenum 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 areconsidered equal. If either floating-point number is NaN (not a number), equalreturns false.
The Not Equal Operator
The not equal operator (!=) is the opposite of the equal operatorfor all types, with a slight variation for floating-point types only. If one ofthe 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 thenormal not equal operator (!=). The other is a negation of the equaloperator !(a==b). Normally, these two forms always evaluate to the samevalue. The exception occurs when evaluating floating-point expressions where oneor both expressions evaluate to NaN and the relational operator in the negationof an expression is <, >, &
lt;=, 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, usethe less than operator (<). The expression on the left is beingevaluated and the expression on the right is the basis of comparison. When theexpression on the left is a lower value than the expression on the right, theresult is true. Otherwise, the result is false. Here's anexample:
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 theleft to the basis expression on the right. When the expression on the left is ahigher 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 orequal 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 theright. When the expression on the left is either the same value as or less thanthe one on the right, less than or equal returns true. This operator isthe opposite of the greater than operator, which means that !(a>b)would produce the same results. The exception is when there's afloating-point expression evaluating to NaN, in which case the result is alwaystrue. 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 theexpression to the left of the operator is the same as or more than theexpression on the right, greater than or equal returns true. Thegreater 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 threetypes of logical operators in C#: bitwise, Boolean, and conditional.
The bitwise logical operators perform Boolean logic on corresponding bits oftwo integral expressions. Valid integral types are the signed and unsigned intand long types. They return a compatible integral result with each bitconforming 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 isevaluated. Finally, the two expressions are evaluated together in the context ofthe Boolean logical operator between them. They return a bool resultcorresponding to the type of operator used.
The conditional logical operators operate much the same way as the Booleanlogical operators with one exception in behavior: Once the first expression isevaluated and found to satisfy the results of the entire expression, the secondexpression is not evaluated. This is efficient because it doesn't makesense to continue evaluating an expression when the result is already known.
The Bitwise AND Operator
The bitwise AND operator (&) compares corresponding bits of twointegrals and returns a result with corresponding bits set to 1 when bothintegrals have 1 bits. When either or both integrals have a 0 bit, thecorresponding 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 oftwo integrals and returns a result with corresponding bits set to 1 if either ofthe integrals have 1 bits in that position. When both integrals have a 0 incorresponding positions, the result is zero in that position. Here's anexample:
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 oftwo integrals and returns a result with corresponding bits set to 1 ifonly one of the integrals has a 1 bit and the other integral has a0 bit in that position. When both integral bits are 1 or whenboth 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
The Boolean AND Operator
The Boolean AND operator (&) evaluates two Boolean expressionsand returns true when both expressions evaluate to true. Otherwise, theresult is false. The result of each expression evaluated must return abool 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 twoBoolean expressions and returns true if either of the expressionsreturns true. When both expressions are false, the result ofthe Boolean inclusive OR evaluation is false. Both expressions evaluated must return a
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 twoBoolean expressions and returns true if only one of the expressionsreturns true. When both expressions are true or bothexpressions are false, the result of the Boolean exclusive ORexpression 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 BooleanAND operator in that it evaluates two expressions and returns true when bothexpressions are true. It is different when the first expression evaluates tofalse. Since both expressions must be true, it's automatically assumed thatif the first expression evaluates to false, the entire expression is false.Therefore, the conditional AND operator returns false and does not evaluate thesecond expression. When the first expression is true, the conditional ANDoperator goes ahead and evaluates the second expression. Here's anexample:
bool inStock = false;
decimal price = 18.95m;
bool buy;
buy = inStock && (price < 20.00m); // buy = false
Notice that price < 20 will never be evaluated.
The Conditional OR Operator
The conditional OR operator (||) is similar to the Boolean inclusiveOR operator (|) in that it evaluates two expressions and returnstrue when either expression is true. The difference is whenthe first expression evaluates to true. Since either expression can betrue to prove that the overall expression is true, theoperator automatically assumes that the entire expression is true whenit finds the first expression is true. Therefore, the conditional ORoperator returns true without evaluating the second expression. Whenthe first expression is false, the conditional OR operator goes aheadand 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 effectsoccur when your program depends on the expression on the right of theconditional logical operator being evaluated. If the expression on the right isnot evaluated, this could cause a hard-to-find bug. The conditional logicaloperators are also called short circuit operators. Take a look at thisexample:
decimal totalSpending = 3692.48m;
decimal avgSpending;
bool onBudget = totalSpending > 4000.00m
&& totalSpending < calcAvg();
Notice that the second half of the expression was not evaluated. IfcalcAvg() was supposed to change the value of a class field for laterprocessing, there would be an error.
Warning
When using conditional AND andconditional OR operators, make sure a program does not depend upon evaluation ofthe right-hand side of the expression, because it may not be evaluated. Suchside effects are likely to cause bugs.
Assignment Operators
This chapter has already demonstrated plenty of examples of the simpleassignment operator in action. This section explains the compound operators andwhat can be expected from them. Basically, the concept is simple. A compoundoperator is a combination of the assignment operator and an arithmetic operator,bitwise logical operator, or Boolean logical operator. Here's anexample:
int total = 7;
total += 3; // total = 10
This is the same as saying: total = total + 3. Table 3.1 shows alist of the available compound assignment operators.
Table 3.1 Compound Assignment Operators
|
Operator |
Function |
|
*= |
Multiplication |
|
/= |
Division |
|
%= |
Remainder |
|
+= |
Addition |
|
-= |
Subtraction |
|
<<= |
Left Shift |
|
>>= |
Right Shift |
|
&= |
AND |
|
^= |
Exclusive OR |
|
|= |
Inclusive OR |
The Ternary Operator
The ternary operator contains three expressions, thus the nameternary. The first expression must be a Boolean expression. When thefirst expression evaluates to true, the value of the second expressionis returned. When the first expression evaluates to false, the value ofthe third expression is returned. This is a concise and short method of making adecision and returning a choice based upon the result of the decision. Theternary operator is often called the conditional operator. Here's anexample:
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 othertypes. 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.
int i = 0;
bool isTest = i is int; // isTest = true
The as Operator
The as operator attempts to perform a conversion on a referencetype. The following example tries to convert the integer i into a string. If theconversion were successful, the object variable obj would hold areference to a string object. When the conversion from an as operatorfails, it assigns null to the receiving reference. That's the casein this example where obj becomes null because i isan 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 constructknown as unsafe code. The sizeof() operator works only inunsafe code. The operator takes a type and returns the type's sizein bytes. Here's an example:
unsafe
{
int intSize = sizeof(int); // intSize = 4
}
The typeof() Operator
The typeof() operator returns a Type object. TheType class holds type information about a value or reference type. Thetypeof() operator is used in various places in C# to discoverinformation about reference and value types. The following example gets typeinformation 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 certainoperations. The following example causes a system error by attempting to assigna 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 ofoverflow conditions, use the unchecked() operator as in thisexample:
short val1 = 20000, val2 = 20000;
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 tobe done inside the code is to annotate the exceptions with thechecked() and unchecked() operators.
Enumeration Expressions
The elements of enumeration expressions evaluate the same as their underlyingtypes. In addition to using normal operators, there are additional methods thatcan be performed with an enum type. An Enum class is used toobtain the majority of functionality shown in this section. Where theEnum class is being used, the capitalized Enum class nameprefixes the method call. The examples in this section refer to the followingenum:
enum Weekday { Mon = 1, Tue, Wed, Thu, Fri, Sat = 10, Sun };
For C++ Programmers
C# enums have muchmore functionality than C++ enums.
As a typed value, the enum must be assigned to a variable of its type. Forexample, the underlying representation of a Weekday enum may default to anintegral value, but it's still a Weekday type. The following line shows thedeclaration and initialization of an enum variable:
Weekday w = Weekday.Mon;
During a Console.WriteLine() method call, enum values are printedwith their names rather than their underlying integral values. Here's anexample:
Console.WriteLine("WeekDay: {0}", w); // WeekDay: Mon
The Format() method returns the string representation of an enumvalue, 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 theFromString() method. The arguments it accepts are the enum type, thestring representation of the value to be converted, and a Boolean condition toverify case. The following example uses the typeof() operator to getthe enum type. The string to be converted is Tue, and the method iscase-sensitive.
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. Thefollowing example shows the GetName() method accepting the enum typeand 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 anenum, use the GetNames() method—plural of the previous method. Thefollowing example shows an array being filled with the names. The method callonly 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 theGetValues() method. The following example shows theGetValues() method accepting an enum type and returning an array ofobjects. Notice that the array is of type objects. In C#, all types are alsoobject 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}&q
uot;, 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 theGetUnderlyingType() method. It accepts an enum type argument, and thereturn 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 theIsDefined() method. It accepts an enum type and an enum value andreturns a Boolean true if the value is defined in the enum. Otherwise, itreturns false. Here's an example:
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 theToObject() method. The following example shows the method accepting anenum type and an integer, and returning an enum of the requested type with thevalue 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 additionalfunctionality that helps make programs more expressive and powerful. Thefollowing 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# ArrayListcollection class. Both are library classes.
The previous example showed the array's Length property. The array typehas 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 array |
|
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 |
|
ToString |
Returns a string representation |
Statements
Statements in C# are single entities that cause a change in theprogram's current state. They're commonly associated with some type ofassignment statement, changing the value of a variable. A statement ends with asemicolon (;). Leave one out and the compiler will issue a prompt notification.Statements may span multiple lines, which could help make your code morereadable, as the following example shows:
decimal closingCosts = loanOrigination
+ appraisal
+ titleSearch
+ insuranceAdvance
+ taxAdvance
+ points
+ realtorCommission
+ whateverElseTheyCanRipYouOffFor;
Had the statement been placed on one line, it would have either continued offthe right side of the page or wrapped around in an inconvenient location. Thisway, each item is visible, lined up nicely, and easier to understand
.
Blocks
Setting off code in blocks clearly delimits the beginning and ending of aunit of work and establishes scope. Begin a block of code with a left-hand brace({), and end it with a right-hand brace (}). Blocks arerequired 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. Thegoto statement allows program control to jump to the place where alabel is defined. A label is any valid identifier followed by a colon (not asemicolon). Here are two examples:
loop: // a label named "loop"
jumphere: // a label named "jumphere"
Declarations
Declarations enable definition and announcement of the existence and natureof program data. There are two forms of declaration in C#: simple declarationand declaration with initialization. A simple declaration takes the followingform:
<type> <identifier>;
The type may be any C# or user-defined type. The identifieris any valid identifier as defined in Chapter 2, "Getting Started withC#."
A declaration with initialization looks like this:
<type> <identifier> = <expression>;
The type and identifier are the same as the previousexample. The equal sign takes the evaluated expression on its right and loads itinto the variable declared on the left. The expression can be any valid C#statement evaluating to the type of variable specified by type. The declarationis a statement followed by a semicolon.
Operator Precedence and Associativity
When evaluating C# expressions, there are certain rules to ensure the outcomeof the evaluation. These rules are governed by precedence and associativity andpreserve the semantics of all C# expressions. Precedence refers to the order inwhich operations should be evaluated. Sub-expressions with higher operatorprecedence are evaluated first.
There are two types of associativity: left and right. Operators with leftassociativity are evaluated from left to right. When an operator has rightassociativity, its expression is evaluated from right to left. For example, theassignment operator is right associative. Therefore, the expression to its rightis 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 andintegrity of computations. One effective rule of thumb when using most operatorsis 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 operationsuse 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. Operatorsin top rows have precedence over operators in lower rows. Operators on the leftin each row have higher precedence over operators to the right in the samerow.
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 |
|
&& |
Left |
|
|| |
Left |
|
?: |
Right |
|
=, *=, /=, %=, +=, -=,<<=, >>=, &=, ^=,|= |
Right |
Summary
This chapter covered the various C# operators—unary, arithmetic,relational operators, and other operators—and provided examples of how touse them.
The unary operators include plus, minus, increment, decrement, logicalcomplement, and bitwise complement operators. Binary operators include thearithmetic, logical, relational and assignment operators. There is a singleternary operator that produces conditional results. C# has a few other operatorsthat don't fit into the any of those categories; they include theis, as, typeof, sizeof, checked,and unchecked operators.
The enum and array types have additional functions that make programs moreexpressive and powerful. I included several examples of enums and a table ofarray methods and properties.
This chapter also described statements, blocks, labels, and declarations, andincluded a section about operator precedence and associativity.
Having mastered the material in this chapter, it's simple to move intological manipulation of program flow.




30. Apr, 2006 by 







No comments yet... Be the first to leave a reply!