Adjust inline-arrays.md based on LDM decisions (#7177)
This commit is contained in:
Родитель
ccde954bdd
Коммит
05105f658b
|
@ -253,6 +253,119 @@ of inline array types.
|
|||
|
||||
Regular definite assignment rules are applicable to variables that have an inline array type.
|
||||
|
||||
### Collection literals
|
||||
|
||||
An inline array type is a valid *constructible collection* target type for a [collection literal](https://github.com/dotnet/csharplang/blob/main/proposals/collection-literals.md).
|
||||
|
||||
For example:
|
||||
``` C#
|
||||
int[5] a = [1, 2, 3, 4, 5]; // initializes anonymous inline array of length 5
|
||||
Buffer10<int> b = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; // initializes user-defined inline array
|
||||
var d = new int[][2] {[11, 12], [21, 22], [31, 32]}; // regular array with an element type of an anonymous inline array type with element type int and length 2
|
||||
```
|
||||
|
||||
The length of the collection literal must match the length of the target inline array type. If the length of the literal
|
||||
is known at compile time and it doesn't match the target length, an error is reported. Otherwise, an exception is going
|
||||
to be thrown at runtime once the mismatch is encountered. The exact exception type is TBD. Some candidates are:
|
||||
System.NotSupportedException, System.InvalidOperationException.
|
||||
|
||||
An instance of an inline array type is a valid expression in a [*spread_element*](https://github.com/dotnet/csharplang/blob/main/proposals/collection-literals.md#detailed-design).
|
||||
|
||||
### Validation of the InlineArrayAttribute applications
|
||||
|
||||
Compiler will validate the following aspects of the InlineArrayAttribute applications:
|
||||
- The target type is a struct
|
||||
- The target type has only one field
|
||||
- Specified length > 0
|
||||
- The target struct doesn't have an explicit layout specified
|
||||
|
||||
### Inline Array elements in an object initializer
|
||||
|
||||
By default, element initialization will not be supported via *initializer_target* of form ```'[' argument_list ']'```
|
||||
(see https://github.com/dotnet/csharpstandard/blob/draft-v8/standard/expressions.md#117153-object-initializers):
|
||||
``` C#
|
||||
static C M2() => new C() { F = {[0] = 111} }; // error CS1913: Member '[0]' cannot be initialized. It is not a field or property.
|
||||
|
||||
class C
|
||||
{
|
||||
public Buffer10<int> F;
|
||||
}
|
||||
```
|
||||
|
||||
However, if the inline array type explicitly defines suitable indexer, object initializer will use it:
|
||||
``` C#
|
||||
static C M2() => new C() { F = {[0] = 111} }; // Ok, indexer is invoked
|
||||
|
||||
class C
|
||||
{
|
||||
public Buffer10<int> F;
|
||||
}
|
||||
|
||||
[System.Runtime.CompilerServices.InlineArray(10)]
|
||||
public struct Buffer10<T>
|
||||
{
|
||||
private T _element0;
|
||||
|
||||
public T this[int i]
|
||||
{
|
||||
get => this[i];
|
||||
set => this[i] = value;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### The foreach statement
|
||||
|
||||
[The foreach statement](https://github.com/dotnet/csharpstandard/blob/draft-v8/standard/statements.md#1295-the-foreach-statement) will be adjusted
|
||||
to allow usage of an inline array type as a collection in a foreach statement.
|
||||
|
||||
For example:
|
||||
``` C#
|
||||
foreach (var a in getBufferAsValue())
|
||||
{
|
||||
WriteLine(a);
|
||||
}
|
||||
|
||||
foreach (var b in getBufferAsWritableVariable())
|
||||
{
|
||||
WriteLine(b);
|
||||
}
|
||||
|
||||
foreach (var c in getBufferAsReadonlyVariable())
|
||||
{
|
||||
WriteLine(c);
|
||||
}
|
||||
|
||||
Buffer10<int> getBufferAsValue() => default;
|
||||
ref Buffer10<int> getBufferAsWritableVariable() => default;
|
||||
ref readonly Buffer10<int> getBufferAsReadonlyVariable() => default;
|
||||
```
|
||||
|
||||
is equivalent to:
|
||||
``` C#
|
||||
Buffer10<int> temp = getBufferAsValue();
|
||||
foreach (var a in (System.ReadOnlySpan<int>)temp)
|
||||
{
|
||||
WriteLine(a);
|
||||
}
|
||||
|
||||
foreach (var b in (System.Span<int>)getBufferAsWritableVariable())
|
||||
{
|
||||
WriteLine(b);
|
||||
}
|
||||
|
||||
foreach (var c in (System.ReadOnlySpan<int>)getBufferAsReadonlyVariable())
|
||||
{
|
||||
WriteLine(c);
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Open design questions
|
||||
|
||||
## Alternatives
|
||||
|
||||
### Inline array type syntax
|
||||
|
||||
The grammar at https://github.com/dotnet/csharpstandard/blob/draft-v8/standard/types.md#821-general will be adjusted as follows:
|
||||
|
@ -365,94 +478,6 @@ var c = new int[][] {{11, 12}, {21, 22}, {31, 32}}; // An error for the nested a
|
|||
var d = new int[][2] {{11, 12}, {21, 22}, {31, 32}}; // An error for the nested array initializer
|
||||
```
|
||||
|
||||
#### Collection literals
|
||||
|
||||
An inline array type is a valid *constructible collection* target type for a [collection literal](https://github.com/dotnet/csharplang/blob/main/proposals/collection-literals.md).
|
||||
|
||||
For example:
|
||||
``` C#
|
||||
int[5] a = [1, 2, 3, 4, 5]; // initializes anonymous inline array of length 5
|
||||
Buffer10<int> b = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; // initializes user-defined inline array
|
||||
var d = new int[][2] {[11, 12], [21, 22], [31, 32]}; // regular array with an element type of an anonymous inline array type with element type int and length 2
|
||||
```
|
||||
|
||||
The length of the collection literal must match the length of the target inline array type. If the length of the literal
|
||||
is known at compile time and it doesn't match the target length, an error is reported. Otherwise, an exception is going
|
||||
to be thrown at runtime once the mismatch is encountered. The exact exception type is TBD. Some candidates are:
|
||||
System.NotSupportedException, System.InvalidOperationException.
|
||||
|
||||
An instance of an inline array type is a valid expression in a [*spread_element*](https://github.com/dotnet/csharplang/blob/main/proposals/collection-literals.md#detailed-design).
|
||||
|
||||
### The foreach statement
|
||||
|
||||
[The foreach statement](https://github.com/dotnet/csharpstandard/blob/draft-v8/standard/statements.md#1295-the-foreach-statement) will be adjusted
|
||||
to allow usage of an inline array type as a collection in a foreach statement.
|
||||
|
||||
For example:
|
||||
``` C#
|
||||
foreach (var a in getBufferAsValue())
|
||||
{
|
||||
WriteLine(a);
|
||||
}
|
||||
|
||||
foreach (var b in getBufferAsWritableVariable())
|
||||
{
|
||||
WriteLine(b);
|
||||
}
|
||||
|
||||
foreach (var c in getBufferAsReadonlyVariable())
|
||||
{
|
||||
WriteLine(c);
|
||||
}
|
||||
|
||||
Buffer10<int> getBufferAsValue() => default;
|
||||
ref Buffer10<int> getBufferAsWritableVariable() => default;
|
||||
ref readonly Buffer10<int> getBufferAsReadonlyVariable() => default;
|
||||
```
|
||||
|
||||
is equivalent to:
|
||||
``` C#
|
||||
Buffer10<int> temp = getBufferAsValue();
|
||||
foreach (var a in (System.ReadOnlySpan<int>)temp)
|
||||
{
|
||||
WriteLine(a);
|
||||
}
|
||||
|
||||
foreach (var b in (System.Span<int>)getBufferAsWritableVariable())
|
||||
{
|
||||
WriteLine(b);
|
||||
}
|
||||
|
||||
foreach (var c in (System.ReadOnlySpan<int>)getBufferAsReadonlyVariable())
|
||||
{
|
||||
WriteLine(c);
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Open design questions
|
||||
|
||||
### Should compiler validate applications of the InlineArrayAttribute?
|
||||
|
||||
Possible things we can check:
|
||||
- The type is a struct (probably just a warning)
|
||||
- Has only one field
|
||||
- Specified length > 0
|
||||
- The struct doesn't have an explicit layout specified
|
||||
|
||||
### Should we support initialization of Inline Array elements in an object initializer?
|
||||
|
||||
``` C#
|
||||
static C M2() => new C() { F = {[0] = 111} };
|
||||
|
||||
class C
|
||||
{
|
||||
public Buffer10<int> F;
|
||||
}
|
||||
```
|
||||
|
||||
## Alternatives
|
||||
|
||||
### Detailed Design (Option 2)
|
||||
|
||||
Note, that for the purpose of this proposal a term "fixed-size buffer" refers to a the proposed "safe fixed-size buffer" feature rather than to a buffer described at https://github.com/dotnet/csharpstandard/blob/draft-v8/standard/unsafe-code.md#228-fixed-size-buffers.
|
||||
|
@ -680,3 +705,11 @@ but can be made into one if necessary. Here’s how that would work:
|
|||
C/C++ has a different notion of fixed-size buffers. For example, there is a notion of "zero-length fixed sized buffers",
|
||||
which is often used as a way to indicate that the data is "variable length". It is not a goal of this proposal to be
|
||||
able to interop with that.
|
||||
|
||||
|
||||
## LDM meetings
|
||||
|
||||
- https://github.com/dotnet/csharplang/blob/main/meetings/2023/LDM-2023-04-03.md#fixed-size-buffers
|
||||
- https://github.com/dotnet/csharplang/blob/main/meetings/2023/LDM-2023-04-10.md#fixed-size-buffers
|
||||
- https://github.com/dotnet/csharplang/blob/main/meetings/2023/LDM-2023-05-01.md#fixed-size-buffers
|
||||
- https://github.com/dotnet/csharplang/blob/main/meetings/2023/LDM-2023-05-03.md#inline-arrays
|
||||
|
|
Загрузка…
Ссылка в новой задаче