Section
|
Category
|
Operators
|
7.6
|
Primary
|
x.y f(x) a[x] x++ x-- new
typeof default checked unchecked delegate
|
7.7
|
Unary
|
+ - ! ~ ++x --x (T)x
|
7.8
|
Multiplicative
|
* / %
|
7.8
|
Additive
|
+ -
|
7.9
|
Shift
|
<< >>
|
7.10
|
Relational and type testing
|
< > <= >= is as
|
7.10
|
Equality
|
== !=
|
7.11
|
Logical AND
|
&
|
7.11
|
Logical XOR
|
^
|
7.11
|
Logical OR
|
|
|
7.12
|
Conditional AND
|
&&
|
7.12
|
Conditional OR
|
||
|
7.13
|
Null coalescing
|
??
|
7.14
|
Conditional
|
?:
|
7.17, 7.15
|
Assignment and lambda expression
|
= *= /= %= += -= <<= >>= &= ^= |=
=>
|
When an operand occurs between two operators with the same precedence, the associativity of the operators controls the order in which the operations are performed:
Except for the assignment operators and the null coalescing operator, all binary operators are left-associative, meaning that operations are performed from left to right. For example, x + y + z is evaluated as (x + y) + z.
The assignment operators, the null coalescing operator and the conditional operator (?:) are right-associative, meaning that operations are performed from right to left. For example, x = y = z is evaluated as x = (y = z).
Precedence and associativity can be controlled using parentheses. For example, x + y * z first multiplies y by z and then adds the result to x, but (x + y) * z first adds x and y and then multiplies the result by z.
Operator overloading
All unary and binary operators have predefined implementations that are automatically available in any expression. In addition to the predefined implementations, user-defined implementations can be introduced by including operator declarations in classes and structs (§10.10). User-defined operator implementations always take precedence over predefined operator implementations: Only when no applicable user-defined operator implementations exist will the predefined operator implementations be considered, as described in §7.3.3 and §7.3.4.
The overloadable unary operators are:
+ - ! ~ ++ -- true false
Although true and false are not used explicitly in expressions (and therefore are not included in the precedence table in §7.3.1), they are considered operators because they are invoked in several expression contexts: boolean expressions (§7.20) and expressions involving the conditional (§7.14), and conditional logical operators (§7.12).
The overloadable binary operators are:
+ - * / % & | ^ << >> == != > < >= <=
Only the operators listed above can be overloaded. In particular, it is not possible to overload member access, method invocation, or the =, &&, ||, ??, ?:, =>, checked, unchecked, new, typeof, default, as, and is operators.
When a binary operator is overloaded, the corresponding assignment operator, if any, is also implicitly overloaded. For example, an overload of operator * is also an overload of operator *=. This is described further in §7.17.2. Note that the assignment operator itself (=) cannot be overloaded. An assignment always performs a simple bit-wise copy of a value into a variable.
Cast operations, such as (T)x, are overloaded by providing user-defined conversions (§6.4).
Element access, such as a[x], is not considered an overloadable operator. Instead, user-defined indexing is supported through indexers (§10.9).
In expressions, operators are referenced using operator notation, and in declarations, operators are referenced using functional notation. The following table shows the relationship between operator and functional notations for unary and binary operators. In the first entry, op denotes any overloadable unary prefix operator. In the second entry, op denotes the unary postfix ++ and -- operators. In the third entry, op denotes any overloadable binary operator.
Operator notation
|
Functional notation
|
op x
|
operator op(x)
|
x op
|
operator op(x)
|
x op y
|
operator op(x, y)
|
User-defined operator declarations always require at least one of the parameters to be of the class or struct type that contains the operator declaration. Thus, it is not possible for a user-defined operator to have the same signature as a predefined operator.
User-defined operator declarations cannot modify the syntax, precedence, or associativity of an operator. For example, the / operator is always a binary operator, always has the precedence level specified in §7.3.1, and is always left-associative.
While it is possible for a user-defined operator to perform any computation it pleases, implementations that produce results other than those that are intuitively expected are strongly discouraged. For example, an implementation of operator == should compare the two operands for equality and return an appropriate bool result.
The descriptions of individual operators in §7.6 through §7.12 specify the predefined implementations of the operators and any additional rules that apply to each operator. The descriptions make use of the terms unary operator overload resolution, binary operator overload resolution, and numeric promotion, definitions of which are found in the following sections.
Do'stlaringiz bilan baham: |