Skip to content

Commit 1985ea0

Browse files
authored
support unsigned right shift operator
1 parent f28c070 commit 1985ea0

1 file changed

Lines changed: 25 additions & 9 deletions

File tree

standard/expressions.md

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ The following operations in C# are subject to binding:
6767
- Element access: `e[e₁,...,eᵥ]`
6868
- Object creation: new `C(e₁,...,eᵥ)`
6969
- Overloaded unary operators: `+`, `-`, `!` (logical negation only), `~`, `++`, `--`, `true`, `false`
70-
- Overloaded binary operators: `+`, `-`, `*`, `/`, `%`, `&`, `&&`, `|`, `||`, `??`, `^`, `<<`, `>>`, `==`, `!=`, `>`, `<`, `>=`, `<=`
71-
- Assignment operators: `=`, `= ref`, `+=`, `-=`, `*=`, `/=`, `%=`, `&=`, `|=`, `^=`, `<<=`, `>>=`, `??=`
70+
- Overloaded binary operators: `+`, `-`, `*`, `/`, `%`, `&`, `&&`, `|`, `||`, `??`, `^`, `<<`, `>>`, `>>>` (static binding only), `==`, `!=`, `>`, `<`, `>=`, `<=`
71+
- Assignment operators: `=`, `= ref`, `+=`, `-=`, `*=`, `/=`, `%=`, `&=`, `|=`, `^=`, `<<=`, `>>=`, `>>>=` (static binding only), `??=`
7272
- Implicit and explicit conversions
7373

7474
When no dynamic expressions are involved, C# defaults to static binding, which means that the compile-time types of subexpressions are used in the selection process. However, when one of the subexpressions in the operations listed above is a dynamic expression, the operation is instead dynamically bound.
@@ -160,7 +160,7 @@ The precedence of an operator is established by the definition of its associated
160160
> | [§12.12](expressions.md#1212-switch-expression) | Switch | `switch { … }` |
161161
> | [§12.13](expressions.md#1213-arithmetic-operators) | Multiplicative | `*` `/` `%` |
162162
> | [§12.13](expressions.md#1213-arithmetic-operators) | Additive | `+` `-` |
163-
> | [§12.14](expressions.md#1214-shift-operators) | Shift | `<<` `>>` |
163+
> | [§12.14](expressions.md#1214-shift-operators) | Shift | `<<` `>>` `>>>` |
164164
> | [§12.15](expressions.md#1215-relational-and-type-testing-operators) | Relational and type-testing | `<` `>` `<=` `>=` `is` `as` |
165165
> | [§12.15](expressions.md#1215-relational-and-type-testing-operators) | Equality | `==` `!=` |
166166
> | [§12.16](expressions.md#1216-logical-operators) | Logical AND | `&` |
@@ -170,7 +170,7 @@ The precedence of an operator is established by the definition of its associated
170170
> | [§12.17](expressions.md#1217-conditional-logical-operators) | Conditional OR | `\|\|` |
171171
> | [§12.18](expressions.md#1218-the-null-coalescing-operator) and12.19](expressions.md#1219-the-throw-expression-operator) | Null coalescing and throw expression | `??` `throw x` |
172172
> |12.21](expressions.md#1221-conditional-operator) | Conditional | `?:` |
173-
> |12.24](expressions.md#1224-assignment-operators) and12.22](expressions.md#1222-anonymous-function-expressions) | Assignment and lambda expression | `=` `= ref` `*=` `/=` `%=` `+=` `-=` `<<=` `>>=` `&=` `^=` `\|=` `=>` `??=` |
173+
> |12.24](expressions.md#1224-assignment-operators) and12.22](expressions.md#1222-anonymous-function-expressions) | Assignment and lambda expression | `=` `= ref` `*=` `/=` `%=` `+=` `-=` `<<=` `>>=` `>>>=` `&=` `^=` `\|=` `=>` `??=` |
174174
>
175175
> *end note*
176176
@@ -201,7 +201,7 @@ Only the operators listed above can be overloaded. In particular, it is not poss
201201
202202
The ***overloadable binary operator***s are:
203203
204-
> `+ - * / % & | ^ << >> == != > < <= >=`
204+
> `+ - * / % & | ^ << >> >>> == != > < <= >=`
205205
206206
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 `isoperators.
207207
@@ -360,7 +360,7 @@ In both of the above cases, a cast expression can be used to explicitly convert
360360
A ***lifted operator*** permits predefined and user-defined operators that operate on a non-nullable value type to also be used with the nullable form of that type. Lifted operators are constructed from predefined and user-defined operators that meet certain requirements, as described in the following:
361361
362362
- For the unary operators `+`, `++`, `-`, `--`, `!` (logical negation), `^`, and `~`, a lifted form of an operator exists if the operand and result types are both non-nullable value types. The lifted form is constructed by adding a single `?modifier to the operand and result types. The lifted operator produces a `null` value if the operand is `null`. Otherwise, the lifted operator unwraps the operand, applies the underlying operator, and wraps the result.
363-
- For the binary operators `+`, `-`, `*`, `/`, `%`, `&`, `|`, `^`, `..`, `<<`, and `>>`, a lifted form of an operator exists if the operand and result types are all non-nullable value types. The lifted form is constructed by adding a single `?modifier to each operand and result type. The lifted operator produces a `null` value if one or both operands are `null` (an exception being the `&` and `|operators of the `bool?` type, as described in12.16.5](expressions.md#12165-nullable-boolean--and--operators)). Otherwise, the lifted operator unwraps the operands, applies the underlying operator, and wraps the result.
363+
- For the binary operators `+`, `-`, `*`, `/`, `%`, `&`, `|`, `^`, `..`, `<<`, `>>`, and `>>>`, a lifted form of an operator exists if the operand and result types are all non-nullable value types. The lifted form is constructed by adding a single `?modifier to each operand and result type. The lifted operator produces a `null` value if one or both operands are `null` (an exception being the `&` and `|operators of the `bool?` type, as described in12.16.5](expressions.md#12165-nullable-boolean--and--operators)). Otherwise, the lifted operator unwraps the operands, applies the underlying operator, and wraps the result.
364364
- For the equality operators `==` and `!=`, a lifted form of an operator exists if the operand types are both non-nullable value types and if the result type is `bool`. The lifted form is constructed by adding a single `?modifier to each operand type. The lifted operator considers two `null` values equal, and a `null` value unequal to any non-`null` value. If both operands are non-`null`, the lifted operator unwraps the operands and applies the underlying operator to produce the `bool` result.
365365
- For the relational operators `<`, `>`, `<=`, and `>=`, a lifted form of an operator exists if the operand types are both non-nullable value types and if the result type is `bool`. The lifted form is constructed by adding a single `?modifier to each operand type. The lifted operator produces the value `false` if one or both operands are `null`. Otherwise, the lifted operator unwraps the operands and applies the underlying operator to produce the `bool` result.
366366
@@ -4498,22 +4498,29 @@ Lifted ([§12.4.8](expressions.md#1248-lifted-operators)) forms of the unlifted
44984498

44994499
## 12.14 Shift operators
45004500

4501-
The `<<` and `>>` operators are used to perform bit-shifting operations.
4501+
The `<<`, `>>`, and `>>>` operators are used to perform bit-shifting operations.
45024502

45034503
```ANTLR
45044504
shift_expression
45054505
: additive_expression
45064506
| shift_expression '<<' additive_expression
45074507
| shift_expression right_shift additive_expression
4508+
| shift_expression unsigned_right_shift additive_expression
45084509
;
45094510
```
45104511

45114512
If an operand of a *shift_expression* has the compile-time type `dynamic`, then the expression is dynamically bound ([§12.3.3](expressions.md#1233-dynamic-binding)). In this case, the compile-time type of the expression is `dynamic`, and the resolution described below will take place at run-time using the run-time type of those operands that have the compile-time type `dynamic`.
45124513

4513-
For an operation of the form `x << count` or `x >> count`, binary operator overload resolution ([§12.4.5](expressions.md#1245-binary-operator-overload-resolution)) is applied to select a specific operator implementation. The operands are converted to the parameter types of the selected operator, and the type of the result is the return type of the operator.
4514+
Dynamic binding uses values of type `enum System.Linq.Expressions.ExpressionType` to communicate binary operator kind to the runtime binder. As there is no enum member specifically representing an unsigned right shift operator, dynamic binding for `>>>` is not supported.
4515+
4516+
For an operation of the form `x << count`, `x >> count`, or `X >>> count`, binary operator overload resolution ([§12.4.5](expressions.md#1245-binary-operator-overload-resolution)) is applied to select a specific operator implementation. The left operand is converted to type `T`, where `T` is the first of `int`, `uint`, `long`, and `ulong` that can fully represent all possible values of the operand. The operation is then performed using the precision of type `T`, and the type of the result is `T`.
45144517

45154518
When declaring an overloaded shift operator, the type of the first operand shall always be the class or struct containing the operator declaration, and the type of the second operand shall always be `int`.
45164519

4520+
The *unsigned_right_shift* operator (`>>>`) shall not be present in an expression tree.
4521+
4522+
> *Note*: The semantics of the predefined `>>>` operator on signed types cannot be accurately represented without adding conversions to an unsigned type and back. *end note*
4523+
45174524
The predefined shift operators are listed below.
45184525

45194526
- Shift left:
@@ -4535,6 +4542,12 @@ The predefined shift operators are listed below.
45354542
uint operator >>(uint x, int count);
45364543
long operator >>(long x, int count);
45374544
ulong operator >>(ulong x, int count);
4545+
int operator >>>(int x, int count);
4546+
uint operator >>>(uint x, int count);
4547+
nint operator >>>(nint x, int count);
4548+
nuint operator >>>(nuint x, int count);
4549+
long operator >>>(long x, int count);
4550+
ulong operator >>>(ulong x, int count);
45384551
```
45394552

45404553
The `>>` operator shifts `x` right by a number of bits computed as described below.
@@ -4543,6 +4556,8 @@ The predefined shift operators are listed below.
45434556

45444557
When `x` is of type `uint`, `nuint`, or `ulong`, the low-order bits of `x` are discarded, the remaining bits are shifted right, and the high-order empty bit positions are set to zero.
45454558

4559+
The `>>>` operator shifts `x` right by a number of bits computed as follows: The low-order bits of `x` are discarded, the remaining bits are shifted right, and the high-order empty bit positions are set to zero.
4560+
45464561
For the predefined operators, the number of bits to shift is computed as follows:
45474562

45484563
- When the type of `x` is `int` or `uint`, the shift count is given by the low-order five bits of `count`. In other words, the shift count is computed from `count & 0x1F`. This also applies when the type of `x` is `nint` or `nuint`, and those types have the same size and representation as `int` and `uint`, respectively.
@@ -6996,6 +7011,7 @@ assignment_operator
69967011
: '=' 'ref'? | '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' |
69977012
'<<=' | '??='
69987013
| right_shift_assignment
7014+
| unsigned_right_shift_assignment
69997015
;
70007016
```
70017017

@@ -7306,7 +7322,7 @@ Only the following constructs are permitted in constant expressions:
73067322
- `checked` and `unchecked` expressions.
73077323
- `nameof` expressions.
73087324
- The predefined `+`, `-`, `!` (logical negation) and `~` unary operators.
7309-
- The predefined `+`, `-`, `*`, `/`, `%`, `<<`, `>>`, `&`, `|`, `^`, `&&`, `||`, `==`, `!=`, `<`, `>`, `<=`, and `>=` binary operators.
7325+
- The predefined `+`, `-`, `*`, `/`, `%`, `<<`, `>>`, `>>>`, `&`, `|`, `^`, `&&`, `||`, `==`, `!=`, `<`, `>`, `<=`, and `>=` binary operators.
73107326
- The `?:` conditional operator.
73117327
- The `!` null-forgiving operator ([§12.8.9](expressions.md#1289-null-forgiving-expressions)).
73127328
- `sizeof` expressions, provided the unmanaged-type is one of the types specified in [§24.6.9](unsafe-code.md#2469-the-sizeof-operator) for which `sizeof` returns a constant value.

0 commit comments

Comments
 (0)