Expressions and Operators

An expression essentially denotes a value. The simplest kinds of expressions are constants and variables. Expressions can be transformed and combined using operators. An operator takes one or more input operands to output a new expression.

Here is an example of a constant expression:

	12

We can use the * operator to combine two operands (the literal expressions 12 and 30), as follows:

	12 * 30

Complex expressions can be built because an operand may itself be an expression, such as the operand (12*30) in the following example:

	1 + (12 * 30)

Operators in C# are classed as unary, binary, or ternary— depending on the number of operands they work on (one, two, or three). The binary operators always use infix notation, where the operator is placed between the two operands.

Primary Expressions

Primary expressions include expressions composed of operators that are intrinsic to the basic plumbing of the language. Here is an example:

	Math.Log (1)

This expression is composed of two primary expressions. The first expression performs a member-lookup (with the . operator), and the second expression performs a method call (with the () operator).

Void Expressions

A void expression is an expression that has no value. For example:

	Console.WriteLine (1)

A void expression—because it has no value—cannot be used as an operand to build more complex expressions:

	1 + Console.WriteLine(1)       // Compile-time error

Assignment Expressions

An assignment expression uses the = operator to assign a variable the result of another expression. For example:

	x = x * 5

An assignment expression is not a void expression. It actually carries the assignment value and thus can be incorporated into another expression. In the following example, the expression assigns 2 to x and 10 to y:

	y = 5 * (x = 2)

This style of expression can be used to initialize multiple values:

	a = b = c = d = 0

The compound assignment operators are syntactic shortcuts that combine assignment with another operator. For example:

	x *= 2          // equivalent to x = x * 2
	x <<= 1         // equivalent to x = x << 1

Operator Precedence and Associativity

When an expression contains multiple operators, precedence and associativity determine the order of evaluation. Operators with higher precedence execute before operators of lower precedence. If the operators have the same precedence, the operator’s associativity determines the order of evaluation.

Precedence

The following expression:

	1 + 2 * 3

is evaluated as follows, as * has a higher precedence than +:

	1 + (2 * 3)

Left-associative operators

Binary operators (except for assignment operators) are left-associative; in other words, they are evaluated from left to right. For example, the following expression:

	8 / 4 / 2

is evaluated as follows due to left associativity:


	( 8 / 4 ) / 2        // 1

You can insert parentheses to change the default order of evaluation:

	8 / ( 4 / 2 )    // 4

Right-associative operators

The assignment operators, the unary operators, and the conditional operator are right-associative; in other words, they are evaluated from right to left. For example:

	int x = 0;
	int y = -~x;     // 1  (Complements first, then negates)
	int z = ~-x;     // -1 (Negates first, then complements)

Operator Table

Table 1-1 lists C#’s operators in order of precedence. Operators in the same category have the same precedence. See the upcoming “Operator Overloading” section for information on how to overload operators.

Table 1-1. C# operators (categories in order of precedence)

Operator symbol

Operator name

Example

Useroverloadable

Primary (highest precedence)

()

Grouping

while(x)

No

.

Member access

x.y

No

->

Pointer to struct (unsafe)

x->y

No

()

Function call

x( )

No

[]

Array/index

a[x]

Via indexer

++

Post-increment

x++

Yes

--

Post-decrement

x--

Yes

new

Create instance

new Foo( )

No

stackalloc

Unsafe stack allocation

stackalloc (10)

No

typeof

Get type from identifier

typeof (int)

No

checked

Integral overflow check on

checked (x)

No

unchecked

Integral overflow check off

unchecked (x)

No

Unary

sizeof

Get size of struct

sizeof (int)

No

+

Positive value of

+x

Yes

-

Negative value of

-x

Yes

!

Not

!x

Yes

~

Bitwise complement

~x

Yes

++

Pre-increment

++x

Yes

--

Pre-decrement

--x

Yes

()

Cast

(int)x

No

*

Value at address (unsafe)

*x

No

&

Address of value (unsafe)

&x

No

Multiplicative

*

Multiply

x * y

Yes

/

Divide

x / y

Yes

%

Remainder

x % y

Yes

Additive

+

Add

x + y

Yes

-

Subtract

x - y

Yes

Shift

<<

Shift left

x >> 1

Yes

>>

Shift right

x << 1

Yes

Relational

<

Less than

x < y

Yes

>

Greater than

x > y

Yes

<=

Less than or equal to

x <= y

Yes

>=

Greater than or equal to

x >= y

Yes

is

Type is or is subclass of

x is y

No

as

Type conversion

x as y

No

Equality

==

Equals

x == y

Yes

!=

Not equals

x != y

Yes

Equality

==

Equals

x == y

Yes

!=

Not equals

x != y

Yes

Logical And

&

And

x & y

Yes

Logical Xor

^

Exclusive Or

x ^ y

Yes

Logical Or

|

Or

x | y

Yes

Conditional And

&&

Conditional And

x && y

Via &

Conditional Or

||

Conditional Or

x || y

Via |

Conditional

?:

Conditional

isTrue ? thenThis : elseThis

No

Assignment

=

Assign

x = y

No

*=

Multiply self by

x *= 2

Via *

/=

Divide self by

x /= 2

Via /

+=

Add to self

x += 2

Via +

-=

Subtract from self

x -= 2

Via -

<<=

Shift self left by

x <<= 2

Via <<

>>=

Shift self right by

x >>= 2

Via >>

&=

And self by

x &= 2

Via &

^=

Exclusive-Or self by

x ^= 2

Via ^

|=

Or self by

x |= 2

Via |

Lambda (lowest precedence)

=>

Lambda

x => x + 1

No

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset