You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: standard/classes.md
+21-14Lines changed: 21 additions & 14 deletions
Original file line number
Diff line number
Diff line change
@@ -412,17 +412,18 @@ type_parameter_constraints
412
412
;
413
413
414
414
primary_constraint
415
-
:class_type
416
-
|'class'
415
+
:class_type'?'?
416
+
|'class''?'?
417
417
|'struct'
418
+
| `notnull`
418
419
|'unmanaged'
419
420
;
420
421
421
422
secondary_constraints
422
-
:interface_type
423
+
:interface_type'?'?
423
424
|type_parameter
424
-
|secondary_constraints','interface_type
425
-
|secondary_constraints','type_parameter
425
+
|secondary_constraints','interface_type'?'?
426
+
|secondary_constraints','type_parameter'?'?
426
427
;
427
428
428
429
constructor_constraint
@@ -434,14 +435,18 @@ Each *type_parameter_constraints_clause* consists of the token `where`, followed
434
435
435
436
The list of constraints given in a `where` clause can include any of the following components, in this order: a single primary constraint, one or more secondary constraints, and the constructor constraint, `new()`.
436
437
437
-
A primary constraint can be a class type, the ***reference type constraint***`class`, the ***value type constraint***`struct`, or the ***unmanaged type constraint***`unmanaged`.
438
+
A primary constraint can be a class type, the ***reference type constraint***`class`, the ***nullable reference type constraint***`class?`, the ***not null*** constraint `notnull`, the ***value type constraint***`struct` or the ***unmanaged type constraint***`unmanaged`.
438
439
439
-
A secondary constraint can be a *type_parameter* or *interface_type*.
440
+
A secondary constraint can be a *type_parameter* or *interface_type*, either optionally followed by `?`.
440
441
441
-
The reference type constraint specifies that a type argument used for the type parameter shall be a reference type. All class types, interface types, delegate types, array types, and type parameters known to be a reference type (as defined below) satisfy this constraint.
442
+
The reference type constraint specifies that a type argument used for the type parameter shall be a non-nullable reference type. All non-nullable class types, non-nullable interface types, non-nullable delegate types, non-nullable array types, and type parameters known to be a non-nullable reference type (as defined below) satisfy this constraint.
443
+
444
+
The nullable reference type constraint specifies that a type argument shall be either a non-nullable reference type or a nullable reference type. All class types, interface types, delegate types, array types, and type parameters known to be a reference type (as defined below) satisfy this constraint.
442
445
443
446
The value type constraint specifies that a type argument used for the type parameter shall be a non-nullable value type. All non-nullable struct types, enum types, and type parameters having the value type constraint satisfy this constraint. Note that although classified as a value type, a nullable value type ([§8.3.12](types.md#8312-nullable-value-types)) does not satisfy the value type constraint. A type parameter having the value type constraint shall not also have the *constructor_constraint*, although it may be used as a type argument for another type parameter with a *constructor_constraint*.
444
447
448
+
The ***not null*** constraint specifies that a type argument used for the type parameter shall be a non-nullable value type or a non-nullable reference type. All non-nullable class types, interface types, delegate types, array types, struct types, enum types, and type parameters known to be a non-nullable value type or non-nullable reference type satisfy this constraint.
449
+
445
450
> *Note*: The `System.Nullable<T>` type specifies the non-nullable value type constraint for `T`. Thus, recursively constructed types of the forms `T??` and `Nullable<Nullable<T>>` are prohibited. *end note*
446
451
447
452
Because `unmanaged` is not a keyword, in *primary_constraint* the unmanaged constraint is always syntactically ambiguous with *class_type*. For compatibility reasons, if a name lookup ([§12.8.4](expressions.md#1284-simple-names)) of the name `unmanaged` succeeds it is treated as a `class_type`. Otherwise it is treated as the unmanaged constraint.
@@ -604,7 +609,9 @@ The ***effective interface set*** of a type parameter `T` is defined as follows
Copy file name to clipboardExpand all lines: standard/types.md
+46Lines changed: 46 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -601,8 +601,20 @@ A type parameter is an identifier designating a value type or reference type tha
601
601
type_parameter
602
602
:identifier
603
603
;
604
+
605
+
nullable_type_parameter
606
+
:non_nullable_non_value_type_parameter'?'
607
+
;
608
+
609
+
non_nullable_non_value_type_parameter
610
+
:type_parameter
611
+
;
604
612
```
605
613
614
+
The *non_nullable_non_value_type_parameter* in *nullable_type_parameter* shall be a type parameter that isn’t constrained to be a value type.
615
+
616
+
In *nullable_type_parameter*, the annotation `?` indicates the intent that type arguments of this type are nullable. The absence of the annotation `?` indicates the intent that type arguments of this type are non-nullable.
617
+
606
618
Since a type parameter can be instantiated with many different type arguments, type parameters have slightly different operations and restrictions than other types.
607
619
608
620
> *Note*: These include:
@@ -705,3 +717,37 @@ An *unmanaged_type* is any type that isn’t a *reference_type*, a *type_paramet
- Any user-defined *struct_type* that is not a constructed type and contains instance fields of *unmanaged_type*s only.
720
+
721
+
## §Generics-and-nullable-placeholder
722
+
723
+
This is a placeholder for text that will be added in the clause on "nullable context" described in `#1124`. I'll rebase and edit once that's done.
724
+
725
+
The distinction between the null states “maybe null” and “maybe default” is subtle and applies to type parameters. A type parameter `T` that has the state “maybe null” means the value is in the domain of valid values for `T`; however, that valid value may include `null`. A “maybe default” state means that the value may be outside the valid domain of values for `T`.
>// The value t here has the state "maybe null". It's possible for T to be instantiated
733
+
>// with string?, in which case null would be within the domain of valid values here. The
734
+
>// assumption though is the value provided here is within the valid values of T. Hence
735
+
>// if T is `string` then null will not be a value, just as we assume that null is not
736
+
>// provided for a normal string parameter
737
+
>voidM<T>(Tt)
738
+
> {
739
+
>// if `T` is a `string`, `t` is not null.
740
+
>// There is no guarantee that default(T) is within the valid values for T hence the
741
+
>// state *must* be "maybe default" and hence local must be T?
742
+
>// For example, default(string) is null, which must be assigned to a string?
743
+
>T?local=default(T);
744
+
> }
745
+
> ```
746
+
>
747
+
>*endexample*
748
+
749
+
The `class?` constraint generates a warning when the `annotations` flag is false.
750
+
751
+
- For any reference type `T`, the annotation `?` in `T?` makes `T?` a nullable type, whereas the unannotated `T` is non-nullable.
752
+
753
+
When the nullable annotation context is enabled, the compiler shall recognize these intents. When the nullable annotation context is disabled, the compiler shall ignore these intents, thereby treating `T` and `T?` in the same (nullable) manner, and generate a warning. (The latter scenario was the only one that existed prior to the addition of nullable reference types.)
0 commit comments