Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions standard/classes.md
Original file line number Diff line number Diff line change
@@ -1,30 +1,30 @@
# 15 Classes

Check warning on line 2 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L2

MDC032::Line length 83 > maximum 81
## 15.1 General

Check warning on line 3 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L3

MDC032::Line length 88 > maximum 81

A class is a data structure that may contain data members (constants and fields), function members (methods, properties, events, indexers, operators, instance constructors, finalizers, and static constructors), and nested types. Class types support inheritance, a mechanism whereby a ***derived class*** can extend and specialize a ***base class***.

Check warning on line 6 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L6

MDC032::Line length 83 > maximum 81
Structs ([§16](structs.md#16-structs)) and interfaces ([§19](interfaces.md#19-interfaces)) have members similar to classes but with certain restrictions. This clause defines the declarations for classes and class members. The clauses for structs and interfaces define the restrictions for those types in terms of the corresponding declarations in class types.

## 15.2 Class declarations

Check warning on line 9 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L9

MDC032::Line length 97 > maximum 81

Check warning on line 10 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L10

MDC032::Line length 83 > maximum 81
### 15.2.1 General

Check warning on line 12 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L12

MDC032::Line length 87 > maximum 81
A *class_declaration* is a *type_declaration* ([§14.8](namespaces.md#148-type-declarations)) that declares a new class.

```ANTLR
class_declaration

Check warning on line 16 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L16

MDC032::Line length 86 > maximum 81
: non_record_class_declaration
| record_class_declaration

Check warning on line 18 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L18

MDC032::Line length 84 > maximum 81
;

Check warning on line 20 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L20

MDC032::Line length 82 > maximum 81
non_record_class_declaration

Check warning on line 21 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L21

MDC032::Line length 93 > maximum 81
: attributes? class_modifier* 'partial'? 'class' identifier
type_parameter_list? class_base? type_parameter_constraints_clause*
class_body
;
```

Check warning on line 27 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L27

MDC032::Line length 82 > maximum 81
There are two kinds of class: ***non-record class***, as declared by *non_record_class_declaration*, and ***record class***, as declared by *record_class_declaration*. A non-record class is the kind of class that C# has supported since the language’s inception. Record classes were added much later and are discussed in [§15.16](classes.md#1516-record-classes). The differences between the two kinds are discussed in [§15.17](classes.md#1517-record-class-and-non-record-class-differences).

A *non_record_class_declaration* consists of an optional set of *attributes* ([§23](attributes.md#23-attributes)), followed by an optional set of *class_modifier*s ([§15.2.2](classes.md#1522-class-modifiers)), followed by an optional `partial` modifier ([§15.2.7](classes.md#1527-partial-type-declarations)), followed by the keyword `class` and an *identifier* that names the class, followed by an optional *type_parameter_list* ([§15.2.3](classes.md#1523-type-parameters)), followed by an optional *class_base* specification ([§15.2.4](classes.md#1524-class-base-specification)), followed by an optional set of *type_parameter_constraints_clause*s ([§15.2.5](classes.md#1525-type-parameter-constraints)), followed by a *class_body* ([§15.2.6](classes.md#1526-class-body)).
Expand All @@ -37,11 +37,11 @@

#### 15.2.2.1 General

A *class_declaration* may optionally include a sequence of class modifiers:

Check warning on line 40 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L40

MDC032::Line length 86 > maximum 81

```ANTLR
class_modifier
: 'new'

Check warning on line 44 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L44

MDC032::Line length 86 > maximum 81
| 'public'
| 'protected'
| 'internal'
Expand Down Expand Up @@ -4967,7 +4967,7 @@

overloadable_binary_operator
: '+' | '-' | '*' | '/' | '%' | '&' | '|' | '^' | '<<'
| right_shift | '==' | '!=' | '>' | '<' | '>=' | '<='
| right_shift | unsigned_right_shift | '==' | '!=' | '>' | '<' | '>=' | '<='
;

conversion_operator_declarator
Expand Down Expand Up @@ -5062,9 +5062,9 @@
The following rules apply to binary operator declarations, where `T` denotes the instance type of the class or struct that contains the operator declaration:

- A binary non-shift operator shall take two parameters, at least one of which shall have type `T` or `T?`, and can return any type.
- A binary `<<` or `>>` operator ([§12.14](expressions.md#1214-shift-operators)) shall take two parameters, the first of which shall have type `T` or `T?` and the second of which shall have type `int` or `int?`, and can return any type.
- A binary `<<`, `>>`, or `>>>` operator ([§12.14](expressions.md#1214-shift-operators)) shall take two parameters, the first of which shall have type `T` or `T?` and the second of which shall have type `int` or `int?`, and can return any type.

The signature of a binary operator consists of the operator token (`+`, `-`, `*`, `/`, `%`, `&`, `|`, `^`, `<<`, `>>`, `==`, `!=`, `>`, `<`, `>=`, or `<=`) and the types of the two parameters. The return type and the names of the parameters are not part of a binary operator’s signature.
The signature of a binary operator consists of the operator token (`+`, `-`, `*`, `/`, `%`, `&`, `|`, `^`, `<<`, `>>`, `>>>`, `==`, `!=`, `>`, `<`, `>=`, or `<=`) and the types of the two parameters. The return type and the names of the parameters are not part of a binary operator’s signature.

Certain binary operators require pair-wise declaration. For every declaration of either operator of a pair, there shall be a matching declaration of the other operator of the pair. Two operator declarations match if identity conversions exist between their return types and their corresponding parameter types. The following operators require pair-wise declaration:

Expand Down
2 changes: 1 addition & 1 deletion standard/documentation-comments.md
Original file line number Diff line number Diff line change
Expand Up @@ -984,7 +984,7 @@ IDs:
"M:Acme.Widget.op_Addition(Acme.Widget,Acme.Widget)"
```

The complete set of binary operator function names used is as follows: `op_Addition`, `op_Subtraction`, `op_Multiply`, `op_Division`, `op_Modulus`, `op_BitwiseAnd`, `op_BitwiseOr`, `op_ExclusiveOr`, `op_LeftShift`, `op_RightShift`, `op_Equality`, `op_Inequality`, `op_LessThan`, `op_LessThanOrEqual`, `op_GreaterThan`, and `op_GreaterThanOrEqual`.
The complete set of binary operator function names used is as follows: `op_Addition`, `op_Subtraction`, `op_Multiply`, `op_Division`, `op_Modulus`, `op_BitwiseAnd`, `op_BitwiseOr`, `op_ExclusiveOr`, `op_LeftShift`, `op_RightShift`, `op_UnsignedRightShift`, `op_Equality`, `op_Inequality`, `op_LessThan`, `op_LessThanOrEqual`, `op_GreaterThan`, and `op_GreaterThanOrEqual`.

**Conversion operators** have a trailing “`~`” followed by the return type. When either the source or destination of a conversion operator is a generic type, the “`<`” and “`">`” characters are replaced by the “`{`” and “`}`” characters, respectively.

Expand Down
34 changes: 25 additions & 9 deletions standard/expressions.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
# 12 Expressions

Check warning on line 1 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L1

MDC032::Line length 83 > maximum 81

Check warning on line 1 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L1

MDC032::Line length 84 > maximum 81

Check warning on line 2 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L2

MDC032::Line length 84 > maximum 81

Check warning on line 2 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L2

MDC032::Line length 85 > maximum 81
## 12.1 General

Check warning on line 3 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L3

MDC032::Line length 85 > maximum 81

Check warning on line 3 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L3

MDC032::Line length 86 > maximum 81

An expression is a sequence of operators and operands. This clause defines the syntax, order of evaluation of operands and operators, and meaning of expressions.

Check warning on line 5 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L5

MDC032::Line length 82 > maximum 81

Check warning on line 5 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L5

MDC032::Line length 102 > maximum 81

Check warning on line 6 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L6

MDC032::Line length 97 > maximum 81

Check warning on line 6 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L6

MDC032::Line length 82 > maximum 81

Check warning on line 6 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L6

MDC032::Line length 82 > maximum 81
An expression *E* is said to ***directly contain*** a subexpression *E₁* if it is not subject to a user-defined conversion [§10.5](conversions.md#105-user-defined-conversions) whose parameter is not of a non-nullable value type, and one of the following conditions holds:

Check warning on line 8 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L8

MDC032::Line length 90 > maximum 81
- *E* is *E₁*.
- If *E* is a parenthesized expression `(E₂)`, and *E₂* directly contains *E₁*.
- If *E* is a null-forgiving operator expression `E₂!`, and *E₂* directly contains *E₁*.
- If *E* is a cast expression `(T)E₂`, and the cast does not subject *E₂* to a non-lifted user-defined conversion whose parameter is not of a non-nullable value type, and *E₂* directly contains *E₁*.

Check warning on line 12 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L12

MDC032::Line length 82 > maximum 81

## 12.2 Expression classifications

Expand Down Expand Up @@ -67,8 +67,8 @@
- Element access: `e[e₁,...,eᵥ]`
- Object creation: new `C(e₁,...,eᵥ)`
- Overloaded unary operators: `+`, `-`, `!` (logical negation only), `~`, `++`, `--`, `true`, `false`
- Overloaded binary operators: `+`, `-`, `*`, `/`, `%`, `&`, `&&`, `|`, `||`, `??`, `^`, `<<`, `>>`, `==`, `!=`, `>`, `<`, `>=`, `<=`
- Assignment operators: `=`, `= ref`, `+=`, `-=`, `*=`, `/=`, `%=`, `&=`, `|=`, `^=`, `<<=`, `>>=`, `??=`
- Overloaded binary operators: `+`, `-`, `*`, `/`, `%`, `&`, `&&`, `|`, `||`, `??`, `^`, `<<`, `>>`, `>>>` (static binding only), `==`, `!=`, `>`, `<`, `>=`, `<=`
- Assignment operators: `=`, `= ref`, `+=`, `-=`, `*=`, `/=`, `%=`, `&=`, `|=`, `^=`, `<<=`, `>>=`, `>>>=` (static binding only), `??=`
- Implicit and explicit conversions

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.
Expand Down Expand Up @@ -160,7 +160,7 @@
> | [§12.12](expressions.md#1212-switch-expression) | Switch | `switch { … }` |
> | [§12.13](expressions.md#1213-arithmetic-operators) | Multiplicative | `*` `/` `%` |
> | [§12.13](expressions.md#1213-arithmetic-operators) | Additive | `+` `-` |
> | [§12.14](expressions.md#1214-shift-operators) | Shift | `<<` `>>` |
> | [§12.14](expressions.md#1214-shift-operators) | Shift | `<<` `>>` `>>>` |
> | [§12.15](expressions.md#1215-relational-and-type-testing-operators) | Relational and type-testing | `<` `>` `<=` `>=` `is` `as` |
> | [§12.15](expressions.md#1215-relational-and-type-testing-operators) | Equality | `==` `!=` |
> | [§12.16](expressions.md#1216-logical-operators) | Logical AND | `&` |
Expand All @@ -170,7 +170,7 @@
> | [§12.17](expressions.md#1217-conditional-logical-operators) | Conditional OR | `\|\|` |
> | [§12.18](expressions.md#1218-the-null-coalescing-operator) and [§12.19](expressions.md#1219-the-throw-expression-operator) | Null coalescing and throw expression | `??` `throw x` |
> | [§12.21](expressions.md#1221-conditional-operator) | Conditional | `?:` |
> | [§12.24](expressions.md#1224-assignment-operators) and [§12.22](expressions.md#1222-anonymous-function-expressions) | Assignment and lambda expression | `=` `= ref` `*=` `/=` `%=` `+=` `-=` `<<=` `>>=` `&=` `^=` `\|=` `=>` `??=` |
> | [§12.24](expressions.md#1224-assignment-operators) and [§12.22](expressions.md#1222-anonymous-function-expressions) | Assignment and lambda expression | `=` `= ref` `*=` `/=` `%=` `+=` `-=` `<<=` `>>=` `>>>=` `&=` `^=` `\|=` `=>` `??=` |
>
> *end note*

Expand Down Expand Up @@ -201,7 +201,7 @@

The ***overloadable binary operator***s 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.

Expand Down Expand Up @@ -358,7 +358,7 @@
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:

- 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.
- 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 in [§12.16.5](expressions.md#12165-nullable-boolean--and--operators)). Otherwise, the lifted operator unwraps the operands, applies the underlying operator, and wraps the result.
- 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 in [§12.16.5](expressions.md#12165-nullable-boolean--and--operators)). Otherwise, the lifted operator unwraps the operands, applies the underlying operator, and wraps the result.
- 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.
- 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.

Expand Down Expand Up @@ -4502,22 +4502,29 @@

## 12.14 Shift operators

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

```ANTLR
shift_expression
: additive_expression
| shift_expression '<<' additive_expression
| shift_expression right_shift additive_expression
| shift_expression unsigned_right_shift additive_expression
;
```

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`.

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.
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.

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`.

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`.

The *unsigned_right_shift* operator (`>>>`) shall not be present in an expression tree.

> *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*

The predefined shift operators are listed below.

- Shift left:
Expand All @@ -4543,6 +4550,12 @@
nuint operator >>(nuint x, int count);
long operator >>(long x, int count);
ulong operator >>(ulong x, int count);
int operator >>>(int x, int count);
uint operator >>>(uint x, int count);
nint operator >>>(nint x, int count);
nuint operator >>>(nuint x, int count);
long operator >>>(long x, int count);
ulong operator >>>(ulong x, int count);
```

The `>>` operator shifts `x` right by a number of bits computed as described below.
Expand All @@ -4551,6 +4564,8 @@

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.

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.

For the predefined operators, the number of bits to shift is computed as follows:

- 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.
Expand Down Expand Up @@ -7416,6 +7431,7 @@
compound_assignment_operator
: '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' | '<<=' | '??='
| right_shift_assignment
| unsigned_right_shift_assignment
;
```

Expand Down Expand Up @@ -7526,7 +7542,7 @@
- `checked` and `unchecked` expressions.
- `nameof` expressions.
- The predefined `+`, `-`, `!` (logical negation) and `~` unary operators.
- The predefined `+`, `-`, `*`, `/`, `%`, `<<`, `>>`, `&`, `|`, `^`, `&&`, `||`, `==`, `!=`, `<`, `>`, `<=`, and `>=` binary operators.
- The predefined `+`, `-`, `*`, `/`, `%`, `<<`, `>>`, `>>>`, `&`, `|`, `^`, `&&`, `||`, `==`, `!=`, `<`, `>`, `<=`, and `>=` binary operators.
- The `?:` conditional operator.
- The `!` null-forgiving operator ([§12.8.9](expressions.md#1289-null-forgiving-expressions)).
- `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.
Expand Down
12 changes: 10 additions & 2 deletions standard/lexical-structure.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
Conceptually speaking, a program is compiled using three steps:

1. Transformation, which converts a file from a particular character repertoire and encoding scheme into a sequence of Unicode characters.
1. Lexical analysis, which translates a stream of Unicode input characters into a stream of tokens.

Check warning on line 10 in standard/lexical-structure.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/lexical-structure.md#L10

MDC032::Line length 85 > maximum 81
1. Syntactic analysis, which translates the stream of tokens into executable code.

Apart from accepting UTF-8 encoded input (as required by [§5](conformance.md#5-conformance), a conforming implementation may choose to accept and transform additional character encoding schemes (such as UTF-16, UTF-32, or non-Unicode character mappings).
Expand Down Expand Up @@ -1049,11 +1049,19 @@
right_shift_assignment
: '>' '>='
;

unsigned_right_shift
: '>' '>' '>'
;

unsigned_right_shift_assignment
: '>' '>' '>='
;
```

> *Note*: *right_shift* and *right_shift_assignment* are parser rules as they do not introduce a new token kind but represent a sequence of two tokens. The *operator_or_punctuator* rule exists for descriptive purposes only and is not used elsewhere in the grammar. *end note*
> *Note*: *right_shift* and *right_shift_assignment* are parser rules as they do not introduce a new token kind but represent a sequence of two tokens. Similarly, *unsigned_right_shift* and *unsigned_right_shift_assignment* are parser rules as they do not introduce a new token kind but represent a sequence of three tokens. The *operator_or_punctuator* rule exists for descriptive purposes only and is not used elsewhere in the grammar. *end note*

*right_shift* is made up of the two tokens `>` and `>`. Similarly, *right_shift_assignment* is made up of the two tokens `>` and `>=`. Unlike other productions in the syntactic grammar, no characters of any kind (not even whitespace) are allowed between the two tokens in each of these productions. These productions are treated specially in order to enable the correct handling of *type_parameter_lists* ([§15.2.3](classes.md#1523-type-parameters)).
*right_shift* is made up of the two tokens `>` and `>`, and *unsigned_right_shift* is made up of the three tokens `>`, `>`, and `>`. Similarly, *right_shift_assignment* is made up of the two tokens `>` and `>=`, and *unsigned_right_shift_assignment* is made up of the three tokens `>`, `>`, and `>=`. Unlike other productions in the syntactic grammar, no characters of any kind (not even whitespace) are allowed between the two tokens in each of these productions. These productions are treated specially in order to enable the correct handling of *type_parameter_lists* ([§15.2.3](classes.md#1523-type-parameters)).

> *Note*: Prior to the addition of generics to C#, `>>` and `>>=` were both single tokens. However, the syntax for generics uses the `<` and `>` characters to delimit type parameters and type arguments. It is often desirable to use nested constructed types, such as `List<Dictionary<string, int>>`. Rather than requiring the programmer to separate the `>` and `>` by a space, the definition of the two *operator_or_punctuator*s was changed. *end note*

Expand Down
Loading