Skip to content
Open
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
58 changes: 50 additions & 8 deletions standard/arrays.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,62 @@

The grammar productions for array types are provided in [§8.2.1](types.md#821-general).

An array type is written as a *non_array_type* followed by one or more *rank_specifier*s.
An array type is written as a *non_array_type* followed by one or more *rank_specifier*s, or an *array_type* followed by a *nullable_type_annotation* followed by one or more *rank_specifier*s. The latter production is used to represent array types where the element type is an array type which is nullable ([§8.9](types.md#89-reference-types-and-nullability)).

A *non_array_type* is any *type* that is not itself an *array_type*.

The rank of an array type is given by the leftmost *rank_specifier* in the *array_type*: A *rank_specifier* indicates that the array is an array with a rank of one plus the number of “`,`” tokens in the *rank_specifier*.

The element type of an array type is the type that results from deleting the leftmost *rank_specifier*:
When determining the rank and element type of array type as specified below, only the *rank_specifier*s in the outer-most production are considered, so in the production `array_type nullable_type_annotation rank_specifier+`, any `rank_specifier` within the `array_type` is ignored.

- An array type of the form `T[R]` is an array with rank `R` and a non-array element type `T`.
- An array type of the form `T[R][R₁]...[Rₓ]` is an array with rank `R` and an element type `T[R₁]...[Rₓ]`.
The rank of an array type is given by the leftmost *rank_specifier* in the *array_type*: A *rank_specifier* indicates that the array is an array with a rank of one plus the number of “`,`” tokens in the *rank_specifier*.

In effect, the *rank_specifier*s are read from left to right *before* the final non-array element type.
The element type of an array type is the type that results from deleting the leftmost *rank_specifier* from the *array_type*.

> *Example*: The type in `T[][,,][,]` is a single-dimensional array of three-dimensional arrays of two-dimensional arrays of `int`. *end example*
> *Example*: The following code shows several variable declarations, including a mixture of single-dimensional arrays, multi-dimensional arrays, and arrays of arrays, with some using nullable reference types. In each case, the rank and element type is described, and then demonstrated with a second variable declaration which is initialized using an element access expression.
>
> <!-- Example: {template:"standalone-console-without-using", name:"ArraysOfArrays", replaceEllipsis:true, customEllipsisReplacements:["default!","default!","default!","default!","default!","default!","default!","default!","default!", "default!"], expectedException:"NullReferenceException"} -->
> ```csharp
> // Rank 1, element type int
> int[] array1 = ...;
> int element1 = array1[0];
>
> // Rank 2, element type int
> int[,] array2 = ...;
> int element2 = array2[0, 1];
>
> // Rank 1, element type int? (Nullable<int>)
> int?[] array3 = ...;
> int? element3 = array3[0];
>
> // Rank 1, element type string? (nullable string)
> string?[] array4 = ...;
> string? element4 = array4[0];
>
> // Rank 1, element type string[,,][,]
> string[][,,][,] array5 = ...;
> string[,,][,] element5 = array5[0];
>
> // Rank 1, element type string; the array itself is nullable
> string[]? array6 = ...;
> string element6 = array6?[0] ?? "";
>
> // Rank 1, element type string[,]?
> string[,]?[] array7 = ...;
> string[,]? element7 = array7[0];
>
> // Rank 3, element type int[]?[,]
> int[]?[,,][,] array8 = ...;
> int[]?[,] element8 = array8[0, 1, 2];
>
> // Rank 1, element type string[,]?[]?[,,]
> string[,]?[]?[][,,] array9 = ...;
> string[,]?[]?[,,] element9 = array9[0];
>
> // Rank 2, element type string[][][,,]
> // Note that this appears the same as the array9 example above other

Check warning on line 85 in standard/arrays.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/arrays.md#L85

MDC032::Line length 83 > maximum 81
> // than for the use of ? but the rank and element type are significantly different.
> string[,][][][,,] array10 = ...;
> string[][][,,] element10 = array10[0, 1];
> ```

At run-time, a value of an array type can be `null` or a reference to an instance of that array type.

Expand Down
28 changes: 25 additions & 3 deletions standard/types.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,22 @@
;

array_type
: non_array_type rank_specifier+
: array_type nullable_type_annotation rank_specifier+
| non_array_type rank_specifier+
;

non_array_type
: non_array_non_nullable_type nullable_type_annotation?
| pointer_type // unsafe code support
;

non_array_non_nullable_type
: value_type
| class_type
| interface_type
| delegate_type
| 'dynamic'
| type_parameter
| pointer_type // unsafe code support
;

rank_specifier
Expand Down Expand Up @@ -732,7 +737,9 @@

> *Note:* The types `R` and `R?` are represented by the same underlying type, `R`. A variable of that underlying type can either contain a reference to an object or be the value `null`, which indicates “no reference.” *end note*

The syntactic distinction between a *nullable reference type* and its corresponding *non-nullable reference type* enables a compiler to generate diagnostics. A compiler must allow the *nullable_type_annotation* as defined in [§8.2.1](types.md#821-general). The diagnostics must be limited to warnings. Neither the presence or absence of nullable annotations, nor the state of the nullable context can change the compile time or runtime behavior of a program except for changes in any diagnostic messages generated at compile time.
The syntactic distinction between a *nullable reference type* and its corresponding *non-nullable reference type* enables a compiler to generate diagnostics. A compiler must allow the *nullable_type_annotation* as defined in [§8.2.1](types.md#821-general). The diagnostics must be limited to warnings. Other than in the meaning of array types, neither the presence or absence of nullable annotations, nor the state of the nullable context can change the compile time or runtime behavior of a program except for changes in any diagnostic messages generated at compile time.

The meaning of array types is significantly impacted by the presence of *nullable_type_annotation* within an *array_type*, as described in [§17.2.1](arrays.md#1721-general).

### 8.9.2 Non-nullable reference types

Expand All @@ -756,6 +763,8 @@

> *Note:* A nullable context where both flags are disabled matches the previous standard behavior for reference types. *end note*

The rank and element of an array type declared using *nullable_type_annotation* is not affected by the nullable context ([§8.9.4](types.md#894-nullable-context)).

#### 8.9.4.2 Nullable disable

When both the warning and annotations flags are disabled, the nullable context is *disabled*.
Expand Down Expand Up @@ -1019,8 +1028,8 @@
> {
> var t = new Test();
> if (t.DisappearingProperty != null)
> {

Check warning on line 1031 in standard/types.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/types.md#L1031

MDC032::Line length 82 > maximum 81
> int len = t.DisappearingProperty.Length; // No warning. A compiler can

Check warning on line 1032 in standard/types.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/types.md#L1032

MDC032::Line length 83 > maximum 81
> // assume property is stateful
> }
> }
Expand Down Expand Up @@ -1106,6 +1115,8 @@

A compiler may follow rules for interface variance ([§19.2.3.3](interfaces.md#19233-variance-conversion)), delegate variance ([§21.4](delegates.md#214-delegate-compatibility)), and array covariance ([§17.6](arrays.md#176-array-covariance)) in determining whether to issue a warning for type conversions.

(See [§17.2.1](arrays.md#1721-general) for the specification of the corresponding non-nullable array type used in `M7` and `M8`.)

> <!-- Example: {template:"code-in-class-lib", name:"NullVariance", ignoredWarnings:["CS8619"]} -->
> ```csharp
> #nullable enable
Expand Down Expand Up @@ -1143,6 +1154,17 @@
> string[] v1 = p; // Warning
> string[] v2 = p!; // No warning
> }
>
> public void M7(string[][,] p)
> {
> string[,]?[] v1 = p; // No warning
> }
>
> public void M8(string[]?[,] p)
> {
> string[,][] v1 = p; // Warning
> string[,][] v2 = p!; // No warning
> }
> }
> ```
>
Expand Down
Loading