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 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).
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
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
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.
The following expression:
1 + 2 * 3
is evaluated as follows, as * has a higher precedence than +:
1 + (2 * 3)
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
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 |
|
No |
. |
Member access |
|
No |
-> |
Pointer to struct (unsafe) |
|
No |
() |
Function call |
|
No |
[] |
Array/index |
|
Via indexer |
++ |
Post-increment |
|
Yes |
-- |
Post-decrement |
|
Yes |
|
Create instance |
| |
|
Unsafe stack allocation |
|
No |
|
Get type from identifier |
|
No |
|
Integral overflow check on |
|
No |
|
|
No | |
Unary |
|
|
|
|
Get size of struct |
|
No |
+ |
Positive value of |
|
Yes |
- |
Negative value of |
|
Yes |
! |
Not |
|
Yes |
~ |
Bitwise complement |
|
Yes |
++ |
Pre-increment |
|
Yes |
-- |
Pre-decrement |
|
Yes |
() |
Cast |
|
No |
* |
Value at address (unsafe) |
|
No |
& |
Address of value (unsafe) |
|
No |
Multiplicative |
|
|
|
* |
Multiply |
|
Yes |
/ |
Divide |
|
Yes |
% |
Remainder |
|
Yes |
Additive |
|
|
|
+ |
Add |
|
Yes |
- |
Subtract |
|
Yes |
Shift |
|
|
|
<< |
Shift left |
|
Yes |
>> |
Shift right |
|
Yes |
Relational |
|
|
|
< |
Less than |
|
Yes |
> |
Greater than |
|
Yes |
<= |
Less than or equal to |
|
Yes |
>= |
Greater than or equal to |
|
Yes |
|
|
No | |
|
Type conversion |
|
No |
Equality |
|
|
|
== |
Equals |
|
Yes |
!= |
Not equals |
|
Yes |
Equality |
|
|
|
== |
Equals |
|
Yes |
!= |
Not equals |
|
Yes |
Logical And |
|
|
|
& |
And |
|
Yes |
Logical Xor |
|
|
|
^ |
Exclusive Or |
|
Yes |
Logical Or |
|
|
|
| |
Or |
|
Yes |
Conditional And |
|
|
|
&& |
Conditional And |
|
Via & |
Conditional Or |
|
|
|
|| |
Conditional Or |
|
Via | |
Conditional |
|
|
|
?: |
Conditional |
|
No |
Assignment |
|
|
|
= |
Assign |
|
No |
*= |
Multiply self by |
|
Via * |
/= |
Divide self by |
|
Via / |
+= |
Add to self |
|
Via + |
-= |
Subtract from self |
|
Via - |
<<= |
Shift self left by |
|
Via << |
>>= |
Shift self right by |
|
Via >> |
&= |
And self by |
|
Via & |
^= |
Exclusive-Or self by |
|
Via ^ |
|= |
Or self by |
|
Via | |
Lambda (lowest precedence) |
|
|
|
=> |
Lambda |
|
No |