diff --git a/standard/README.md b/standard/README.md index d414ddba4..6664ef2b3 100644 --- a/standard/README.md +++ b/standard/README.md @@ -237,8 +237,6 @@ - [§10.2.19](conversions.md#10219-implicit-object-creation-conversions) Implicit object-creation conversions - [§10.2.20](conversions.md#10220-implicit-conditional-expression-conversions) Implicit conditional expression conversions - [§10.2.21](conversions.md#10221-anonymous-function-type-conversion) Anonymous function type conversion - - [§10.2.22](conversions.md#10222-implicit-collection-expression-conversions) Implicit collection expression conversions - - [§10.2.23](conversions.md#10223-implicit-inline-array-conversions) Implicit inline array conversions - [§10.3](conversions.md#103-explicit-conversions) Explicit conversions - [§10.3.1](conversions.md#1031-general) General - [§10.3.2](conversions.md#1032-explicit-numeric-conversions) Explicit numeric conversions @@ -369,9 +367,8 @@ - [§12.8.12](expressions.md#12812-element-access) Element access - [§12.8.12.1](expressions.md#128121-general) General - [§12.8.12.2](expressions.md#128122-array-access) Array access - - [§12.8.12.3](expressions.md#128123-inline-array-element-access) Inline array element access - - [§12.8.12.4](expressions.md#128124-string-access) String access - - [§12.8.12.5](expressions.md#128125-indexer-access) Indexer access + - [§12.8.12.3](expressions.md#128123-string-access) String access + - [§12.8.12.4](expressions.md#128124-indexer-access) Indexer access - [§12.8.13](expressions.md#12813-null-conditional-element-access) Null Conditional Element Access - [§12.8.14](expressions.md#12814-this-access) This access - [§12.8.15](expressions.md#12815-base-access) Base access @@ -392,7 +389,6 @@ - [§12.8.22](expressions.md#12822-stack-allocation) Stack allocation - [§12.8.23](expressions.md#12823-the-nameof-operator) The nameof operator - [§12.8.24](expressions.md#12824-anonymous-method-expressions) Anonymous method expressions - - [§12.8.25](expressions.md#12825-collection-expressions) Collection expressions - [§12.9](expressions.md#129-unary-operators) Unary operators - [§12.9.1](expressions.md#1291-general) General - [§12.9.2](expressions.md#1292-unary-plus-operator) Unary plus operator @@ -619,7 +615,7 @@ - [§15.6.2.3.2](classes.md#156232-input-parameters) Input parameters - [§15.6.2.3.3](classes.md#156233-reference-parameters) Reference parameters - [§15.6.2.3.4](classes.md#156234-output-parameters) Output parameters - - [§15.6.2.4](classes.md#15624-parameter-arrays) Parameter arrays + - [§15.6.2.4](classes.md#15624-parameter-collections) Parameter collections - [§15.6.3](classes.md#1563-static-and-instance-methods) Static and instance methods - [§15.6.4](classes.md#1564-virtual-methods) Virtual methods - [§15.6.5](classes.md#1565-override-methods) Override methods @@ -662,7 +658,6 @@ - [§15.11.3](classes.md#15113-instance-variable-initializers) Instance variable initializers - [§15.11.4](classes.md#15114-constructor-execution) Constructor execution - [§15.11.5](classes.md#15115-default-constructors) Default constructors - - [§15.11.6](classes.md#15116-primary-constructors) Primary constructors - [§15.12](classes.md#1512-static-constructors) Static constructors - [§15.13](classes.md#1513-finalizers) Finalizers - [§15.14](classes.md#1514-async-functions) Async Functions @@ -685,23 +680,22 @@ - [§15.15.6.2](classes.md#151562-the-getenumerator-or-getasyncenumerator-method) The GetEnumerator or GetAsyncEnumerator method - [§15.16](classes.md#1516-record-classes) Record classes - [§15.16.1](classes.md#15161-general) General - - [§15.16.2](classes.md#15162-class-members) Class members - - [§15.16.3](classes.md#15163-instance-constructors) Instance constructors - - [§15.16.4](classes.md#15164-implicit-record-class-members) Implicit record class members - - [§15.16.4.1](classes.md#151641-general) General - - [§15.16.4.2](classes.md#151642-copy-constructors) Copy constructors - - [§15.16.4.3](classes.md#151643-equality-members) Equality members - - [§15.16.4.4](classes.md#151644-copy-and-clone-members) Copy and clone members - - [§15.16.4.5](classes.md#151645-printing-members) Printing members - - [§15.16.4.6](classes.md#151646-positional-record-class-members) Positional record class members - - [§15.16.4.6.1](classes.md#1516461-general) General - - [§15.16.4.6.2](classes.md#1516462-primary-constructor) Primary constructor - - [§15.16.4.6.3](classes.md#1516463-properties) Properties - - [§15.16.4.6.4](classes.md#1516464-deconstruct) Deconstruct - - [§15.17](classes.md#1517-declaring-a-collection-type) Declaring a collection type - - [§15.17.1](classes.md#15171-general) General - - [§15.17.2](classes.md#15172-collection-construction) Collection construction - - [§15.18](classes.md#1518-record-class-and-non-record-class-differences) Record class and non-record class differences + - [§15.16.2](classes.md#15162-class-base-specification) Class base specification + - [§15.16.3](classes.md#15163-record-class-body) Record class body + - [§15.16.4](classes.md#15164-class-members) Class members + - [§15.16.5](classes.md#15165-instance-constructors) Instance constructors + - [§15.16.6](classes.md#15166-implicit-record-class-members) Implicit record class members + - [§15.16.6.1](classes.md#151661-general) General + - [§15.16.6.2](classes.md#151662-copy-constructors) Copy constructors + - [§15.16.6.3](classes.md#151663-equality-members) Equality members + - [§15.16.6.4](classes.md#151664-copy-and-clone-members) Copy and clone members + - [§15.16.6.5](classes.md#151665-printing-members) Printing members + - [§15.16.6.6](classes.md#151666-positional-record-class-members) Positional record class members + - [§15.16.6.6.1](classes.md#1516661-general) General + - [§15.16.6.6.2](classes.md#1516662-primary-constructor) Primary constructor + - [§15.16.6.6.3](classes.md#1516663-properties) Properties + - [§15.16.6.6.4](classes.md#1516664-deconstruct) Deconstruct + - [§15.17](classes.md#1517-record-class-and-non-record-class-differences) Record class and non-record class differences - [§16](structs.md#16-structs) Structs - [§16.1](structs.md#161-general) General - [§16.2](structs.md#162-struct-declarations) Struct declarations @@ -714,51 +708,50 @@ - [§16.3](structs.md#163-struct-members) Struct members - [§16.3.1](structs.md#1631-general) General - [§16.3.2](structs.md#1632-readonly-members) Readonly members - - [§16.4](structs.md#164-primary-constructors) Primary constructors - - [§16.5](structs.md#165-record-structs) Record structs - - [§16.5.1](structs.md#1651-general) General - - [§16.5.2](structs.md#1652-struct-members) Struct members - - [§16.5.3](structs.md#1653-implicit-record-struct-members) Implicit record struct members - - [§16.5.3.1](structs.md#16531-general) General - - [§16.5.3.2](structs.md#16532-primary-constructors) Primary constructors - - [§16.5.3.3](structs.md#16533-equality-members) Equality members - - [§16.5.3.4](structs.md#16534-printing-members) Printing members - - [§16.5.3.5](structs.md#16535-positional-record-struct-members) Positional record struct members - - [§16.5.3.5.1](structs.md#165351-general) General - - [§16.5.3.5.2](structs.md#165352-primary-constructor) Primary constructor - - [§16.5.3.5.3](structs.md#165353-properties) Properties - - [§16.5.3.5.4](structs.md#165354-deconstruct) Deconstruct - - [§16.6](structs.md#166-inline-arrays) Inline arrays - - [§16.7](structs.md#167-record-struct-and-non-record-struct-differences) Record struct and non-record struct differences - - [§16.8](structs.md#168-class-and-struct-differences) Class and struct differences - - [§16.8.1](structs.md#1681-general) General - - [§16.8.2](structs.md#1682-value-semantics) Value semantics - - [§16.8.3](structs.md#1683-inheritance) Inheritance - - [§16.8.4](structs.md#1684-assignment) Assignment - - [§16.8.5](structs.md#1685-default-values) Default values - - [§16.8.6](structs.md#1686-boxing-and-unboxing) Boxing and unboxing - - [§16.8.7](structs.md#1687-meaning-of-this) Meaning of this - - [§16.8.8](structs.md#1688-fields) Fields - - [§16.8.8.1](structs.md#16881-field-initializers) Field initializers - - [§16.8.8.2](structs.md#16882-ref-fields) Ref fields - - [§16.8.9](structs.md#1689-constructors) Constructors - - [§16.8.10](structs.md#16810-static-constructors) Static constructors - - [§16.8.11](structs.md#16811-properties) Properties - - [§16.8.12](structs.md#16812-methods) Methods - - [§16.8.13](structs.md#16813-indexers) Indexers - - [§16.8.14](structs.md#16814-events) Events - - [§16.8.15](structs.md#16815-safe-context-constraint) Safe context constraint - - [§16.8.15.1](structs.md#168151-general) General - - [§16.8.15.2](structs.md#168152-parameter-safe-context) Parameter safe context - - [§16.8.15.3](structs.md#168153-local-variable-safe-context) Local variable safe context - - [§16.8.15.4](structs.md#168154-field-safe-context) Field safe context - - [§16.8.15.5](structs.md#168155-operators) Operators - - [§16.8.15.6](structs.md#168156-method-and-property-invocation) Method and property invocation - - [§16.8.15.7](structs.md#168157-method-arguments-must-match) Method arguments must match - - [§16.8.15.8](structs.md#168158-infer-safe-context-of-declaration-expressions) Infer safe-context of declaration expressions - - [§16.8.15.9](structs.md#168159-object-initializer-safe-context) Object initializer safe context - - [§16.8.15.10](structs.md#1681510-stackalloc) stackalloc - - [§16.8.15.11](structs.md#1681511-constructor-invocations) Constructor invocations + - [§16.4](structs.md#164-record-structs) Record structs + - [§16.4.1](structs.md#1641-general) General + - [§16.4.2](structs.md#1642-struct-members) Struct members + - [§16.4.3](structs.md#1643-record-struct-body) Record struct body + - [§16.4.4](structs.md#1644-implicit-record-struct-members) Implicit record struct members + - [§16.4.4.1](structs.md#16441-general) General + - [§16.4.4.2](structs.md#16442-primary-constructors) Primary constructors + - [§16.4.4.3](structs.md#16443-equality-members) Equality members + - [§16.4.4.4](structs.md#16444-printing-members) Printing members + - [§16.4.4.5](structs.md#16445-positional-record-struct-members) Positional record struct members + - [§16.4.4.5.1](structs.md#164451-general) General + - [§16.4.4.5.2](structs.md#164452-primary-constructor) Primary constructor + - [§16.4.4.5.3](structs.md#164453-properties) Properties + - [§16.4.4.5.4](structs.md#164454-deconstruct) Deconstruct + - [§16.5](structs.md#165-record-struct-and-non-record-struct-differences) Record struct and non-record struct differences + - [§16.6](structs.md#166-class-and-struct-differences) Class and struct differences + - [§16.6.1](structs.md#1661-general) General + - [§16.6.2](structs.md#1662-value-semantics) Value semantics + - [§16.6.3](structs.md#1663-inheritance) Inheritance + - [§16.6.4](structs.md#1664-assignment) Assignment + - [§16.6.5](structs.md#1665-default-values) Default values + - [§16.6.6](structs.md#1666-boxing-and-unboxing) Boxing and unboxing + - [§16.6.7](structs.md#1667-meaning-of-this) Meaning of this + - [§16.6.8](structs.md#1668-fields) Fields + - [§16.6.8.1](structs.md#16681-field-initializers) Field initializers + - [§16.6.8.2](structs.md#16682-ref-fields) Ref fields + - [§16.6.9](structs.md#1669-constructors) Constructors + - [§16.6.10](structs.md#16610-static-constructors) Static constructors + - [§16.6.11](structs.md#16611-properties) Properties + - [§16.6.12](structs.md#16612-methods) Methods + - [§16.6.13](structs.md#16613-indexers) Indexers + - [§16.6.14](structs.md#16614-events) Events + - [§16.6.15](structs.md#16615-safe-context-constraint) Safe context constraint + - [§16.6.15.1](structs.md#166151-general) General + - [§16.6.15.2](structs.md#166152-parameter-safe-context) Parameter safe context + - [§16.6.15.3](structs.md#166153-local-variable-safe-context) Local variable safe context + - [§16.6.15.4](structs.md#166154-field-safe-context) Field safe context + - [§16.6.15.5](structs.md#166155-operators) Operators + - [§16.6.15.6](structs.md#166156-method-and-property-invocation) Method and property invocation + - [§16.6.15.7](structs.md#166157-method-arguments-must-match) Method arguments must match + - [§16.6.15.8](structs.md#166158-infer-safe-context-of-declaration-expressions) Infer safe-context of declaration expressions + - [§16.6.15.9](structs.md#166159-object-initializer-safe-context) Object initializer safe context + - [§16.6.15.10](structs.md#1661510-stackalloc) stackalloc + - [§16.6.15.11](structs.md#1661511-constructor-invocations) Constructor invocations - [§17](arrays.md#17-arrays) Arrays - [§17.1](arrays.md#171-general) General - [§17.2](arrays.md#172-array-types) Array types @@ -883,8 +876,6 @@ - [§23.5.12](attributes.md#23512-required-member-attributes) Required member attributes - [§23.5.12.1](attributes.md#235121-the-setsrequiredmembers-attribute) The SetsRequiredMembers attribute - [§23.5.12.2](attributes.md#235122-the-requiredmember-attribute) The RequiredMember attribute - - [§23.5.13](attributes.md#23513-the-collectionbuilder-attribute) The CollectionBuilder attribute - - [§23.5.14](attributes.md#23514-the-inlinearray-attribute) The InlineArray attribute - [§23.6](attributes.md#236-attributes-for-interoperation) Attributes for interoperation - [§24](unsafe-code.md#24-unsafe-code) Unsafe code - [§24.1](unsafe-code.md#241-general) General diff --git a/standard/arrays.md b/standard/arrays.md index 7a55bc748..fdbc7079b 100644 --- a/standard/arrays.md +++ b/standard/arrays.md @@ -144,7 +144,7 @@ When an array type `S[]` implements `IList`, some of the members of the imple ## 17.3 Array creation -Array instances are created by *array_creation_expression*s ([§12.8.17.5](expressions.md#128175-delegate-creation-expressions)) or by field or local variable declarations that include an *array_initializer* ([§17.7](arrays.md#177-array-initializers)). Array instances can also be created implicitly as part of evaluating an argument list involving a parameter array ([§15.6.2.4](classes.md#15624-parameter-arrays)). +Array instances are created by *array_creation_expression*s ([§12.8.17.4](expressions.md#128174-array-creation-expressions)) or by field or local variable declarations that include an *array_initializer* ([§17.7](arrays.md#177-array-initializers)). Array instances can also be created implicitly as part of evaluating an argument list involving a parameter collection ([§15.6.2.4](classes.md#15624-parameter-collections)). When an array instance is created, the rank and length of each dimension are established and then remain constant for the entire lifetime of the instance. In other words, it is not possible to change the rank of an existing array instance, nor is it possible to resize its dimensions. @@ -314,5 +314,5 @@ When an array creation expression includes both explicit dimension lengths and a A warning shall be produced for a *variable_initializer* when all the following conditions are true: -- The variable initializer represents an implicit or explicit identity conversion of a primary constructor parameter ([§15.11.6](classes.md#15116-primary-constructors)); +- The variable initializer represents an implicit or explicit identity conversion of a primary constructor parameter (§prim-constructor); - The primary constructor parameter is captured into the state of the enclosing type. diff --git a/standard/attributes.md b/standard/attributes.md index 4ac871c4c..ab1ff4569 100644 --- a/standard/attributes.md +++ b/standard/attributes.md @@ -512,8 +512,8 @@ A number of attributes affect the language in some way. These attributes include - `System.Runtime.CompilerServices.InterpolatedStringHandlerAttribute` and `System.Runtime.CompilerServices.InterpolatedStringHandlerArgumentAttribute`, which are used to declare a custom interpolated string expression handler ([§23.5.11.1](attributes.md#235111-custom-interpolated-string-expression-handlers)) and to call one of its constructors, respectively. - `System.Diagnostics.CodeAnalysis.UnscopedRefAttribute` ([§23.5.8](attributes.md#2358-the-unscopedref-attribute)), which allows an otherwise implicitly scoped ref to be treated as not being scoped. - `System.Diagnostics.CodeAnalysis.SetsRequiredMembersAttribute` ([§23.5.12.1](attributes.md#235121-the-setsrequiredmembers-attribute)) and `System.Runtime.CompilerServices.RequiredMemberAttribute` ([§23.5.12.2](attributes.md#235122-the-requiredmember-attribute)), which are used in required-member contexts ([§15.7.1](classes.md#1571-general)). -- `System.Runtime.CompilerServices.CollectionBuilderAttribute` ([§23.5.13](attributes.md#23513-the-collectionbuilder-attribute)), which designates a collection type as having a collection-creation method. -- `System.Runtime.CompilerServices.InlineArrayAttribute` ([§23.5.14](attributes.md#23514-the-inlinearray-attribute)), which marks a struct type as an inline array type ([§16.6](structs.md#166-inline-arrays)). +- `System.Runtime.CompilerServices.CollectionBuilderAttribute` (§collection-builder-attr), which designates a collection type as having a collection-creation method. +- `System.Runtime.CompilerServices.InlineArrayAttribute` (§InlineArrayAttribute), which marks a struct type as an inline array type (§InlineArray). The Nullable static analysis attributes ([§23.5.7](attributes.md#2357-code-analysis-attributes)) can improve the correctness of warnings generated for nullabilities and null states ([§8.9.5](types.md#895-nullabilities-and-null-states)). @@ -1579,9 +1579,9 @@ This attribute indicates that the constructor it decorates sets all required mem This attribute indicates that the current type has one or more required members ([§15.7.1](classes.md#1571-general)), or that a specific member of that type is required. However, it is an error for this attribute to be used explicitly. Instead, the presence of the modifier `required` results in the type or member being treated as if it were decorated with this attribute. -### 23.5.13 The CollectionBuilder attribute +### §collection-builder-attr The CollectionBuilder attribute -This attribute designates a collection type as having a collection-creation method ([§15.17.1](classes.md#15171-general)). +This attribute designates a collection type as having a collection-creation method (§declaring-a-collection-type-general). The constructor takes a builder type and the name of the method to be invoked to construct an instance of the collection type. @@ -1589,9 +1589,9 @@ The attribute can be applied to a class, struct, ref struct, or interface. The a The builder type shall be a non-generic class or struct. -### 23.5.14 The InlineArray attribute +### §InlineArrayAttribute The InlineArray attribute -This attribute is used to identify a non-record struct as an inline array type. For further information and examples of its use, see [§16.6](structs.md#166-inline-arrays). +This attribute is used to identify a non-record struct as an inline array type. For further information and examples of its use, see §InlineArray. ## 23.6 Attributes for interoperation diff --git a/standard/basic-concepts.md b/standard/basic-concepts.md index 2fe81f80c..6eac27138 100644 --- a/standard/basic-concepts.md +++ b/standard/basic-concepts.md @@ -123,7 +123,7 @@ The application startup and termination process is semantically equivalent to th - Awaiting ([§12.9.9](expressions.md#1299-await-expressions)) the result of invoking the entry-point method, if its return type is a `Task` type. - In either case if the entry point requires an argument the application parameter array is supplied as its value. -> *Note*: Invoking the entry-point method will cause the static constructor, if any, of the enclosing type to be executed first ([§15.12](classes.md#1512-static-constructors), [§16.8.10](structs.md#16810-static-constructors)). *end note* +> *Note*: Invoking the entry-point method will cause the static constructor, if any, of the enclosing type to be executed first ([§15.12](classes.md#1512-static-constructors), [§16.6.10](structs.md#16610-static-constructors)). *end note* - The application is terminated - If the run results in an `int` value it serves as the termination status code; @@ -154,9 +154,9 @@ There are several different types of declaration spaces, as described in the fol - Within all compilation units of a program, *namespace_member_declaration*s within *namespace_declaration*s that have the same fully qualified namespace name are members of a single combined declaration space. Per [§14.3](namespaces.md#143-namespace-declarations), this includes *file_scoped_namespace_declaration*s. - Each *compilation_unit* and *namespace_body* has an ***alias declaration space***. Each *extern_alias_directive* and *using_alias_directive* of the *compilation_unit* or *namespace_body* contributes a member to the alias declaration space ([§14.6.2](namespaces.md#1462-using-alias-directives)). - Each non-partial class, struct, or interface declaration creates a new declaration space. Each partial class, struct, or interface declaration contributes to a declaration space shared by all matching parts in the same program ([§16.2.4](structs.md#1624-partial-modifier)). Names are introduced into this declaration space through *class_member_declaration*s, *struct_member_declaration*s, *interface_member_declaration*s, or *type_parameter*s. Except for overloaded instance constructor declarations and static constructor declarations, a class, struct, or interface cannot contain a member declaration with the same name as the class, struct, or interface. A class, struct, or interface permits the declaration of overloaded methods and indexers. Furthermore, a class or struct permits the declaration of overloaded instance constructors and operators. For example, a class, struct, or interface may contain multiple method declarations with the same name, provided these method declarations differ in their signature ([§7.5](basic-concepts.md#75-signatures-and-overloading)). Note that base classes do not contribute to the declaration space of a class, and base interfaces do not contribute to the declaration space of an interface. Thus, a derived class or interface is allowed to declare a member with the same name as an inherited member. Such a member is said to ***hide*** the inherited member. -- Each delegate declaration creates a new declaration space. Names are introduced into this declaration space through parameters (*fixed_parameter*s and *parameter_array*s) and *type_parameter*s. +- Each delegate declaration creates a new declaration space. Names are introduced into this declaration space through parameters (*fixed_parameter*s and *parameter_collection*s) and *type_parameter*s. - Each enumeration declaration creates a new declaration space. Names are introduced into this declaration space through *enum_member_declarations*. -- Each method declaration, property declaration, property accessor declaration, indexer declaration, indexer accessor declaration, operator declaration, instance constructor declaration, anonymous function, and local function creates a new declaration space called a ***local variable declaration space***. Names are introduced into this declaration space through parameters (*fixed_parameter*s and *parameter_array*s) and *type_parameter*s. The set and init accessor for a property or an indexer introduce the name `value` as a parameter. The body of the function member, anonymous function, or local function, if any, is considered to be nested within the local variable declaration space. When a local variable declaration space and a nested local variable declaration space contain elements with the same name, within the scope of the nested local name, the outer local name is hidden ([§7.6.1](basic-concepts.md#761-general)) by the nested local name. +- Each method declaration, property declaration, property accessor declaration, indexer declaration, indexer accessor declaration, operator declaration, instance constructor declaration, anonymous function, and local function creates a new declaration space called a ***local variable declaration space***. Names are introduced into this declaration space through parameters (*fixed_parameter*s and *parameter_collection*s) and *type_parameter*s. The set and init accessor for a property or an indexer introduce the name `value` as a parameter. The body of the function member, anonymous function, or local function, if any, is considered to be nested within the local variable declaration space. When a local variable declaration space and a nested local variable declaration space contain elements with the same name, within the scope of the nested local name, the outer local name is hidden ([§7.6.1](basic-concepts.md#761-general)) by the nested local name. > *Note*: Discard parameters of anonymous functions ([§12.22.2](expressions.md#12222-anonymous-function-signatures)) do not introduce names into any declaration space. *end note* - Additional local variable declaration spaces may occur within member declarations, anonymous functions and local functions. Names are introduced into these declaration spaces through *pattern*s, *declaration_expression*s, *declaration_statement*s and *exception_specifier*s. Local variable declaration spaces may be nested, but it is an error for a local variable declaration space and a nested local variable declaration space to contain elements with the same name. Thus, within a nested declaration space it is not possible to declare a local variable, local function or constant with the same name as a parameter, type parameter, local variable, local function or constant in an enclosing declaration space. It is possible for two declaration spaces to contain elements with the same name as long as neither declaration space contains the other. Local declaration spaces are created by the following constructs: - Each *variable_initializer* in a field and property declaration introduces its own local variable declaration space, that is not nested within any other local variable declaration space. diff --git a/standard/classes.md b/standard/classes.md index 355c8fcb1..58b495d4f 100644 --- a/standard/classes.md +++ b/standard/classes.md @@ -36,13 +36,13 @@ non_record_class_with_positional_members ; ``` -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.18](classes.md#1518-record-class-and-non-record-class-differences). +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* can have one of two almost identical forms: *non_record_class_without_positional_members* and *non_record_class_with_positional_members*. A *non_record_class_without_positional_members* 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)). -A *non_record_class_with_positional_members* has the same syntax but requires a *delimited_parameter_list*, as shown above in that grammar rule. For a discussion of *delimited_parameter_list*, see [§15.11.6](classes.md#15116-primary-constructors). +A *non_record_class_with_positional_members* has the same syntax but requires a *delimited_parameter_list*, as shown above in that grammar rule. For a discussion of *delimited_parameter_list*, see §prim-constructor. A class having a required member ([§15.7.1](classes.md#1571-general)) directly (that is, not through inheritance) shall be treated as if it were decorated with the attribute `System.Runtime.CompilerServices.RequiredMemberAttribute` ([§23.5.12.2](attributes.md#235122-the-requiredmember-attribute)). @@ -227,7 +227,7 @@ interface_type_list A warning shall be produced for an in or by-value argument in a *base_argument_list* when all the following conditions are true: -- The argument represents an implicit or explicit identity conversion of a primary constructor parameter ([§15.11.6](classes.md#15116-primary-constructors)); +- The argument represents an implicit or explicit identity conversion of a primary constructor parameter (§prim-constructor); - The argument is not part of an expanded params argument; - The primary constructor parameter is captured into the state of the enclosing type. @@ -888,7 +888,7 @@ The handling of attributes specified on the type or type parameters of different ### 15.3.1 General -The members of a class consist of the members introduced by its *class_member_declaration*s, the members inherited from the direct base class, and any members implicitly provided by the implementation ([§15.16.4](classes.md#15164-implicit-record-class-members)). +The members of a class consist of the members introduced by its *class_member_declaration*s, the members inherited from the direct base class, and any members implicitly provided by the implementation ([§15.16.6](classes.md#15166-implicit-record-class-members)). ```ANTLR class_member_declaration @@ -1746,7 +1746,7 @@ The value of a field is obtained in an expression using a *simple_name* ([§12.8 A field declaration that declares multiple fields is equivalent to multiple declarations of single fields with the same attributes, modifiers, and type. -> *Note*: Inside a `ref struct`, a field may also be declared as a reference variable; see [§16.8.8.2](structs.md#16882-ref-fields). *end note* +> *Note*: Inside a `ref struct`, a field may also be declared as a reference variable; see [§16.6.8.2](structs.md#16682-ref-fields). *end note* @@ -2133,7 +2133,7 @@ A variable initializer for an instance field cannot reference the instance being ### 15.6.1 General -[§15.6](classes.md#156-methods) and its subclauses cover method declarations in classes. That text is augmented by information about declaring methods in structs ([§16.8](structs.md#168-class-and-struct-differences)) and interfaces ([§19.4.3](interfaces.md#1943-interface-methods)). +[§15.6](classes.md#156-methods) and its subclauses cover method declarations in classes. That text is augmented by information about declaring methods in structs ([§16.6](structs.md#166-class-and-struct-differences)) and interfaces ([§19.4.3](interfaces.md#1943-interface-methods)). A ***method*** is a member that implements a computation or action that can be performed by an object or class. Methods are declared using *method_declaration*s: @@ -2219,7 +2219,7 @@ Grammar notes: > *Note*: The overlapping of, and priority between, alternatives here is solely for descriptive convenience; the grammar rules could be elaborated to remove the overlap. ANTLR, and other grammar systems, adopt the same convenience and so *method_body* has the specified semantics automatically. *end note* -A *method_declaration* may include a set of *attributes* ([§23](attributes.md#23-attributes)) and one of the permitted kinds of declared accessibility ([§15.3.6](classes.md#1536-access-modifiers)), the `new` ([§15.3.5](classes.md#1535-the-new-modifier)), `static` ([§15.6.3](classes.md#1563-static-and-instance-methods)), `virtual` ([§15.6.4](classes.md#1564-virtual-methods)), `override` ([§15.6.5](classes.md#1565-override-methods)), `sealed` ([§15.6.6](classes.md#1566-sealed-methods)), `abstract` ([§15.6.7](classes.md#1567-abstract-methods)), `extern` ([§15.6.8](classes.md#1568-external-methods)) and `async` ([§15.14](classes.md#1514-async-functions)) modifiers. Additionally a *method_declaration* that is contained directly by a *struct_declaration* may include the `readonly` modifier ([§16.8.12](structs.md#16812-methods)). +A *method_declaration* may include a set of *attributes* ([§23](attributes.md#23-attributes)) and one of the permitted kinds of declared accessibility ([§15.3.6](classes.md#1536-access-modifiers)), the `new` ([§15.3.5](classes.md#1535-the-new-modifier)), `static` ([§15.6.3](classes.md#1563-static-and-instance-methods)), `virtual` ([§15.6.4](classes.md#1564-virtual-methods)), `override` ([§15.6.5](classes.md#1565-override-methods)), `sealed` ([§15.6.6](classes.md#1566-sealed-methods)), `abstract` ([§15.6.7](classes.md#1567-abstract-methods)), `extern` ([§15.6.8](classes.md#1568-external-methods)) and `async` ([§15.14](classes.md#1514-async-functions)) modifiers. Additionally a *method_declaration* that is contained directly by a *struct_declaration* may include the `readonly` modifier ([§16.6.12](structs.md#16612-methods)). A *method_declaration* has a valid combination of modifiers if all of the following are true. (These rules are modified slightly in the context of an interface; see [§19.4.1](interfaces.md#1941-general).): @@ -2287,8 +2287,8 @@ delimited_parameter_list parameter_list : fixed_parameters - | fixed_parameters ',' parameter_array - | parameter_array + | fixed_parameters ',' parameter_collection + | parameter_collection ; fixed_parameters @@ -2316,12 +2316,12 @@ parameter_mode_modifier | 'in' ; -parameter_array - : attributes? 'params' array_type identifier +parameter_collection + : attributes? 'params' type identifier ; ``` -The parameter list consists of one or more comma-separated parameters of which only the last may be a *parameter_array*. +The parameter list consists of one or more comma-separated parameters of which only the last may be a *parameter_collection*. A *fixed_parameter* consists of an optional set of *attributes* ([§23](attributes.md#23-attributes)); an optional `this` modifier; an optional `scoped` modifier; an optional `in`, `out`, `ref` modifier, or `ref readonly`; a *type*; an *identifier*; and an optional *default_argument*. Each *fixed_parameter* declares a parameter of the given type with the given name. The `this` modifier designates the method as an extension method and is only allowed on the first parameter of a static method in a non-generic, non-nested static class. If the parameter is a `struct` type or a type parameter constrained to a `struct`, the `this` modifier may be combined with the `ref`, `ref readonly`, or `in` modifier, but not the `out` modifier. Extension methods are further described in [§15.6.10](classes.md#15610-extension-methods). A *fixed_parameter* with a *default_argument* is known as an ***optional parameter***, whereas a *fixed_parameter* without a *default_argument* is a ***required parameter***. A required parameter shall not appear after an optional parameter in a *parameter_list*. @@ -2339,9 +2339,32 @@ The *expression* shall be implicitly convertible by an identity or nullable conv If optional parameters occur in an implementing partial method declaration, a compiler should give a warning, since any default arguments are removed per [§15.6.9](classes.md#1569-partial-methods). If optional parameters occur in an explicit interface member implementation ([§19.6.2](interfaces.md#1962-explicit-interface-member-implementations)), a single-parameter indexer declaration ([§15.9](classes.md#159-indexers)), or in an operator declaration ([§15.10.1](classes.md#15101-general)) a compiler should give a warning, since these members can never be invoked in a way that permits arguments to be omitted. -A *parameter_array* consists of an optional set of *attributes* ([§23](attributes.md#23-attributes)), a `params` modifier, an *array_type*, and an *identifier*. A parameter array declares a single parameter of the given array type with the given name. The *array_type* of a parameter array shall be a single-dimensional array type ([§17.2](arrays.md#172-array-types)). In a method invocation, a parameter array permits either a single argument of the given array type to be specified, or it permits zero or more arguments of the array element type to be specified. Parameter arrays are described further in [§15.6.2.4](classes.md#15624-parameter-arrays). - -A *parameter_array* may occur after an optional parameter, but cannot have a default value – the omission of arguments for a *parameter_array* would instead result in the creation of an empty array. +A *parameter_collection* consists of an optional set of *attributes* ([§23](attributes.md#23-attributes)), a `params` modifier, a *type*, and an *identifier*. A parameter collection declares a single parameter of the given array type with the given name. The *type* of a parameter collection shall be one of the following valid target types for a collection expression: + +- A single dimensional array type `T[]`, in which case the element type is `T` +- A span type + - `System.Span` + - `System.ReadOnlySpan` + in which cases the element type is `T` +- A type with an appropriate collection-creation method (§collection-construction) that can be invoked with no additional arguments, which is at least as accessible as the declaring member, and with a corresponding element type resulting from that determination +- A struct or class type that implements `System.Collections.IEnumerable` where: + - The type has a constructor that can be invoked with no arguments, and the constructor is at least as accessible as the declaring member. + - The type has an instance (not an extension) method `Add` where: + - The method can be invoked with a single value argument. + - If the method is generic, the type arguments can be inferred from the argument. + - The method is at least as accessible as the declaring member. + In which case the element type is the iteration type ([§13.9.5.1]( statements.md#13951-general)) of *type*. +- An interface type + - `System.Collections.Generic.IEnumerable` + - `System.Collections.Generic.IReadOnlyCollection` + - `System.Collections.Generic.IReadOnlyList` + - `System.Collections.Generic.ICollection` + - `System.Collections.Generic.IList` + in which case the element type is `T`. + +In a method invocation, a parameter collection permits either a single argument of the given array type to be specified, or it permits zero or more arguments of the array element type to be specified. Parameter collections are described further in [§15.6.2.4](classes.md#15624-parameter-collections). + +A *parameter_collection* may occur after an optional parameter, but cannot have a default value – the omission of arguments for a *parameter_collection* would instead result in the creation of an empty collection. > *Example*: The following illustrates different kinds of parameters: > @@ -2359,7 +2382,7 @@ A *parameter_array* may occur after an optional parameter, but cannot have a def > ) { } > ``` > -> In the *parameter_list* for `M`, `i` is a required `ref` parameter, `d` is a required value parameter, `b`, `s`, `o` and `t` are optional value parameters and `a` is a parameter array. +> In the *parameter_list* for `M`, `i` is a required `ref` parameter, `d` is a required value parameter, `b`, `s`, `o` and `t` are optional value parameters and `a` is a parameter collection. > > *end example* @@ -2374,7 +2397,7 @@ The following kinds of parameters exist: - Output parameters ([§15.6.2.3.4](classes.md#156234-output-parameters)). - Reference parameters ([§15.6.2.3.3](classes.md#156233-reference-parameters)). - Reference readonly parameters, which are reference parameters that also have the `readonly` modifier. -- Parameter arrays ([§15.6.2.4](classes.md#15624-parameter-arrays)). +- Parameter collections ([§15.6.2.4](classes.md#15624-parameter-collections)). > *Note*: As described in [§7.5](basic-concepts.md#75-signatures-and-overloading), the `in`, `out`, `ref`, and `ref readonly` modifiers are part of a method’s signature, but the `params` and `scoped` modifiers are not. *end note* @@ -2552,26 +2575,26 @@ An output parameter is implicitly `scoped` ([§9.7.3](variables.md#973-the-scope > > *end example* -#### 15.6.2.4 Parameter arrays +#### 15.6.2.4 Parameter collections -A parameter declared with a `params` modifier is a parameter array. If a parameter list includes a parameter array, it shall be the last parameter in the list and it shall be of a single-dimensional array type. +A parameter declared with a `params` modifier is a parameter collection. -> *Example*: The types `string[]` and `string[][]` can be used as the type of a parameter array, but the type `string[,]` cannot. *end example* +> *Example*: The types `string[]` and `string[][]` can be used as the type of a parameter collection, but the type `string[,]` cannot. *end example* > *Note*: It is not possible to combine the `params` modifier with the modifiers `in`, `out`, or `ref`. *end note* -A parameter array permits arguments to be specified in one of two ways in a method invocation: +A parameter collection permits arguments to be specified in one of two ways in a method invocation: -- The argument given for a parameter array can be a single expression that is implicitly convertible ([§10.2](conversions.md#102-implicit-conversions)) to the parameter array type. In this case, the parameter array acts precisely like a value parameter. -- Alternatively, the invocation can specify zero or more arguments for the parameter array, where each argument is an expression that is implicitly convertible ([§10.2](conversions.md#102-implicit-conversions)) to the element type of the parameter array. In this case, the invocation creates an instance of the parameter array type with a length corresponding to the number of arguments, initializes the elements of the array instance with the given argument values, and uses the newly created array instance as the actual argument. +- The argument given for a parameter collection can be a single expression that is implicitly convertible ([§10.2](conversions.md#102-implicit-conversions)) to the parameter collection type. In this case, the parameter collection acts precisely like a value parameter. +- Alternatively, the invocation can specify zero or more arguments for the parameter collection, where each argument is an expression that is implicitly convertible ([§10.2](conversions.md#102-implicit-conversions)) to the element type of the parameter collection. In this case, the invocation creates an instance of the parameter collection type according to the rules specified in §collection-expressions as though the arguments were used as expression elements in a collection expression in the same order, and uses the newly created collection instance as the actual argument. When constructing the collection instance, the original unconverted arguments are used. -Except for allowing a variable number of arguments in an invocation, a parameter array is precisely equivalent to a value parameter ([§15.6.2.2](classes.md#15622-value-parameters)) of the same type. +Except for allowing a variable number of arguments in an invocation, a parameter collection is precisely equivalent to a value parameter ([§15.6.2.2](classes.md#15622-value-parameters)) of the same type. > *Example*: The example > -> +> > ```csharp > class Test > { @@ -2616,11 +2639,13 @@ Except for allowing a variable number of arguments in an invocation, a parameter > > The fourth and fifth invocations pass a three-element and an empty collection expression, respectively. *end example* -When performing overload resolution, a method with a parameter array might be applicable, either in its normal form or in its expanded form ([§12.6.4.2](expressions.md#12642-applicable-function-member)). The expanded form of a method is available only if the normal form of the method is not applicable and only if an applicable method with the same signature as the expanded form is not already declared in the same type. +When performing overload resolution, a method with a parameter collection might be applicable, either in its normal form or in its expanded form ([§12.6.4.2](expressions.md#12642-applicable-function-member)). The expanded form of a method is available only if the normal form of the method is not applicable and only if an applicable method with the same signature as the expanded form is not already declared in the same type. + +A potential ambiguity arises between the normal form and the expanded form of the method with a single parameter collection argument when it can be used as the parameter collection itself and as the element of the parameter collection at the same time. The ambiguity presents no problem, however, since it can be resolved by inserting a cast or using a collection expression, if needed. > *Example*: The example > -> +> > ```csharp > class Test > { @@ -2654,17 +2679,17 @@ When performing overload resolution, a method with a parameter array might be ap > F(object[]) > ``` > -> In the example, two of the possible expanded forms of the method with a parameter array are already included in the class as regular methods. These expanded forms are therefore not considered when performing overload resolution, and the first and third method invocations thus select the regular methods. When a class declares a method with a parameter array, it is not uncommon to also include some of the expanded forms as regular methods. By doing so, it is possible to avoid the allocation of an array instance that occurs when an expanded form of a method with a parameter array is invoked. +> In the example, two of the possible expanded forms of the method with a parameter collection are already included in the class as regular methods. These expanded forms are therefore not considered when performing overload resolution, and the first and third method invocations thus select the regular methods. When a class declares a method with a parameter collection, it is not uncommon to also include some of the expanded forms as regular methods. By doing so, it is possible to avoid the allocation of a collection instance that occurs when an expanded form of a method with a parameter collection is invoked. > > *end example* -> An array is a reference type, so the value passed for a parameter array can be `null`. +> An array is a reference type, so the value passed for a parameter collection can be `null`. > > *Example*: The example: > -> +> > ```csharp > class Test > { @@ -2690,11 +2715,11 @@ When performing overload resolution, a method with a parameter array might be ap > > *end example* -When the type of a parameter array is `object[]`, a potential ambiguity arises between the normal form of the method and the expanded form for a single `object` parameter. The reason for the ambiguity is that an `object[]` is itself implicitly convertible to type `object`. The ambiguity presents no problem, however, since it can be resolved by inserting a cast if needed. +When the type of a parameter collection is `object[]`, a potential ambiguity arises between the normal form of the method and the expanded form for a single `object` parameter. The reason for the ambiguity is that an `object[]` is itself implicitly convertible to type `object`. The ambiguity presents no problem, however, since it can be resolved by inserting a cast if needed. > *Example*: The example > -> +> > ```csharp > class Test > { @@ -3541,7 +3566,7 @@ ref_property_body *unsafe_modifier* ([§24.2](unsafe-code.md#242-unsafe-contexts)) is only available in unsafe code ([§24](unsafe-code.md#24-unsafe-code)). -A *property_declaration* may include a set of *attributes* ([§23](attributes.md#23-attributes)) and any one of the permitted kinds of declared accessibility ([§15.3.6](classes.md#1536-access-modifiers)), the `new` ([§15.3.5](classes.md#1535-the-new-modifier)), `static` ([§15.7.2](classes.md#1572-static-and-instance-properties)), `virtual` ([§15.6.4](classes.md#1564-virtual-methods), [§15.7.6](classes.md#1576-virtual-sealed-override-and-abstract-accessors)), `override` ([§15.6.5](classes.md#1565-override-methods), [§15.7.6](classes.md#1576-virtual-sealed-override-and-abstract-accessors)), `sealed` ([§15.6.6](classes.md#1566-sealed-methods)), `abstract` ([§15.6.7](classes.md#1567-abstract-methods), [§15.7.6](classes.md#1576-virtual-sealed-override-and-abstract-accessors)) and `extern` ([§15.6.8](classes.md#1568-external-methods)). Additionally a *property_declaration* that is contained directly by a *struct_declaration* may include the `readonly` modifier ([§16.8.11](structs.md#16811-properties)). +A *property_declaration* may include a set of *attributes* ([§23](attributes.md#23-attributes)) and any one of the permitted kinds of declared accessibility ([§15.3.6](classes.md#1536-access-modifiers)), the `new` ([§15.3.5](classes.md#1535-the-new-modifier)), `static` ([§15.7.2](classes.md#1572-static-and-instance-properties)), `virtual` ([§15.6.4](classes.md#1564-virtual-methods), [§15.7.6](classes.md#1576-virtual-sealed-override-and-abstract-accessors)), `override` ([§15.6.5](classes.md#1565-override-methods), [§15.7.6](classes.md#1576-virtual-sealed-override-and-abstract-accessors)), `sealed` ([§15.6.6](classes.md#1566-sealed-methods)), `abstract` ([§15.6.7](classes.md#1567-abstract-methods), [§15.7.6](classes.md#1576-virtual-sealed-override-and-abstract-accessors)) and `extern` ([§15.6.8](classes.md#1568-external-methods)). Additionally a *property_declaration* that is contained directly by a *struct_declaration* may include the `readonly` modifier ([§16.6.11](structs.md#16611-properties)). - The first declares a non-ref-valued property. Its value has type *type*. This kind of property may be readable and/or writeable. - The second declares a ref-valued property. Its value is a *variable_reference* ([§9.5](variables.md#95-variable-references)), that may be `readonly`, to a variable of type *type*. This kind of property is only readable. @@ -3660,7 +3685,7 @@ For a ref-valued property the *ref_get_accessor_declaration* consists optional a The use of *accessor_modifier*s is governed by the following restrictions: - An *accessor_modifier* shall not be used in an explicit interface member implementation. -- The *accessor_modifier* `readonly` is permitted only in a *property_declaration* or *indexer_declaration* that is contained directly by a *struct_declaration* ([§16.8.11](structs.md#16811-properties), [§16.8.13](structs.md#16813-indexers)). +- The *accessor_modifier* `readonly` is permitted only in a *property_declaration* or *indexer_declaration* that is contained directly by a *struct_declaration* ([§16.6.11](structs.md#16611-properties), [§16.6.13](structs.md#16613-indexers)). - For a property or indexer that has no `override` modifier, an *accessor_modifier* is permitted only if the property or indexer has both a get and set or init accessor, and then is permitted only on one of those accessors. - For a property or indexer that includes an `override` modifier, an accessor shall match the *accessor_modifier*, if any, of the accessor being overridden. - The *accessor_modifier* shall declare an accessibility that is strictly more restrictive than the declared accessibility of the property or indexer itself. To be precise: @@ -4568,7 +4593,7 @@ remove_accessor_declaration *unsafe_modifier* ([§24.2](unsafe-code.md#242-unsafe-contexts)) is only available in unsafe code ([§24](unsafe-code.md#24-unsafe-code)). -An *event_declaration* may include a set of *attributes* ([§23](attributes.md#23-attributes)) and any one of the permitted kinds of declared accessibility ([§15.3.6](classes.md#1536-access-modifiers)), the `new` ([§15.3.5](classes.md#1535-the-new-modifier)), `static` ([§15.6.3](classes.md#1563-static-and-instance-methods), [§15.8.4](classes.md#1584-static-and-instance-events)), `virtual` ([§15.6.4](classes.md#1564-virtual-methods), [§15.8.5](classes.md#1585-virtual-sealed-override-and-abstract-accessors)), `override` ([§15.6.5](classes.md#1565-override-methods), [§15.8.5](classes.md#1585-virtual-sealed-override-and-abstract-accessors)), `sealed` ([§15.6.6](classes.md#1566-sealed-methods)), `abstract` ([§15.6.7](classes.md#1567-abstract-methods), [§15.8.5](classes.md#1585-virtual-sealed-override-and-abstract-accessors)) and `extern` ([§15.6.8](classes.md#1568-external-methods)) modifiers. Additionally an *event_declaration* that is contained directly by a *struct_declaration* may include the `readonly` modifier ([§16.8.12](structs.md#16812-methods)). +An *event_declaration* may include a set of *attributes* ([§23](attributes.md#23-attributes)) and any one of the permitted kinds of declared accessibility ([§15.3.6](classes.md#1536-access-modifiers)), the `new` ([§15.3.5](classes.md#1535-the-new-modifier)), `static` ([§15.6.3](classes.md#1563-static-and-instance-methods), [§15.8.4](classes.md#1584-static-and-instance-events)), `virtual` ([§15.6.4](classes.md#1564-virtual-methods), [§15.8.5](classes.md#1585-virtual-sealed-override-and-abstract-accessors)), `override` ([§15.6.5](classes.md#1565-override-methods), [§15.8.5](classes.md#1585-virtual-sealed-override-and-abstract-accessors)), `sealed` ([§15.6.6](classes.md#1566-sealed-methods)), `abstract` ([§15.6.7](classes.md#1567-abstract-methods), [§15.8.5](classes.md#1585-virtual-sealed-override-and-abstract-accessors)) and `extern` ([§15.6.8](classes.md#1568-external-methods)) modifiers. Additionally an *event_declaration* that is contained directly by a *struct_declaration* may include the `readonly` modifier ([§16.6.12](structs.md#16612-methods)). Event declarations are subject to the same rules as method declarations ([§15.6](classes.md#156-methods)) with regard to valid combinations of modifiers. @@ -4851,7 +4876,7 @@ ref_indexer_body *unsafe_modifier* ([§24.2](unsafe-code.md#242-unsafe-contexts)) is only available in unsafe code ([§24](unsafe-code.md#24-unsafe-code)). -An *indexer_declaration* may include a set of *attributes* ([§23](attributes.md#23-attributes)) and any one of the permitted kinds of declared accessibility ([§15.3.6](classes.md#1536-access-modifiers)), the `new` ([§15.3.5](classes.md#1535-the-new-modifier)), `virtual` ([§15.6.4](classes.md#1564-virtual-methods)), `override` ([§15.6.5](classes.md#1565-override-methods)), `sealed` ([§15.6.6](classes.md#1566-sealed-methods)), `abstract` ([§15.6.7](classes.md#1567-abstract-methods)) and `extern` ([§15.6.8](classes.md#1568-external-methods)) modifiers. Additionally an *indexer_declaration* that is contained directly by a *struct_declaration* may include the `readonly` modifier ([§16.8.12](structs.md#16812-methods)). +An *indexer_declaration* may include a set of *attributes* ([§23](attributes.md#23-attributes)) and any one of the permitted kinds of declared accessibility ([§15.3.6](classes.md#1536-access-modifiers)), the `new` ([§15.3.5](classes.md#1535-the-new-modifier)), `virtual` ([§15.6.4](classes.md#1564-virtual-methods)), `override` ([§15.6.5](classes.md#1565-override-methods)), `sealed` ([§15.6.6](classes.md#1566-sealed-methods)), `abstract` ([§15.6.7](classes.md#1567-abstract-methods)) and `extern` ([§15.6.8](classes.md#1568-external-methods)) modifiers. Additionally an *indexer_declaration* that is contained directly by a *struct_declaration* may include the `readonly` modifier ([§16.6.12](structs.md#16612-methods)). - The first declares a non-ref-valued indexer. Its value has type *type*. This kind of indexer may be readable and/or writeable. - The second declares a ref-valued indexer. Its value is a *variable_reference* ([§9.5](variables.md#95-variable-references)), that may be `readonly`, to a variable of type *type*. This kind of indexer is only readable. @@ -5023,7 +5048,7 @@ When an indexer declaration includes an `extern` modifier, the indexer is said t Indexers and properties are very similar in concept, but differ in the following ways: - A property is identified by its name, whereas an indexer is identified by its signature. -- A property is accessed through a *simple_name* ([§12.8.4](expressions.md#1284-simple-names)) or a *member_access* ([§12.8.7](expressions.md#1287-member-access)), whereas an indexer element is accessed through an *element_access* ([§12.8.12.5](expressions.md#128125-indexer-access)). +- A property is accessed through a *simple_name* ([§12.8.4](expressions.md#1284-simple-names)) or a *member_access* ([§12.8.7](expressions.md#1287-member-access)), whereas an indexer element is accessed through an *element_access* ([§12.8.12.4](expressions.md#128124-indexer-access)). - A property can be a static member, whereas an indexer is always an instance member. - A get accessor of a property corresponds to a method with no parameters, whereas a get accessor of an indexer corresponds to a method with the same parameter list as the indexer. - A set accessor of a property corresponds to a method with a single parameter named `value`, whereas a set accessor of an indexer corresponds to a method with the same parameter list as the indexer, plus an additional parameter named `value`. @@ -5630,7 +5655,7 @@ If overload resolution is unable to determine a unique best candidate for the ba > > *end example* -### 15.11.6 Primary constructors +### §prim-constructor Primary constructors For a class type with a *delimited_parameter_list* the implementation shall provide a public constructor whose signature corresponds to the value parameters, if any, of the type declaration. This constructor is called the ***primary constructor*** for that type, and causes the implicitly declared default constructor, to be suppressed. It is an error to have a primary constructor and an explicit constructor with the same signature in the type. If the type declaration does not include a *delimited_parameter_list*, no primary constructor is provided. @@ -6367,25 +6392,25 @@ At most only one partial type declaration of a partial record class may provide Parameters in *delimited_parameter_list* shall not have `ref`, `out` or `this` modifiers; however, `in` and `params` modifiers are permitted. -### 15.16.2 Class members +### 15.16.4 Class members It is an error for a member of a record class to be named `Clone`. It is an error for an instance field of a record class to have an unsafe type. -### 15.16.3 Instance constructors +### 15.16.5 Instance constructors -A positional record class ([§15.16.1](classes.md#15161-general)) has a primary constructor; see [§15.16.4.6.2](classes.md#1516462-primary-constructor) for more information. +A positional record class ([§15.16.1](classes.md#15161-general)) has a primary constructor; see [§15.16.6.6.2](classes.md#1516662-primary-constructor) for more information. -### 15.16.4 Implicit record class members +### 15.16.6 Implicit record class members -#### 15.16.4.1 General +#### 15.16.6.1 General Certain members are provided by the implementation unless a member with a matching signature is declared in the *class_body*, or an accessible concrete, non-virtual member with a matching signature is inherited. A matching member prevents the implementation from providing that member only, not any other provided members. Two members are considered matching if they have the same signature or would be considered hiding in an inheritance scenario. The members provided by the implementation are described in the following subclauses. -#### 15.16.4.2 Copy constructors +#### 15.16.6.2 Copy constructors A ***copy constructor*** for a type `T` is a constructor having a single parameter of type `T`. The purpose of a copy constructor is to copy the state from the parameter to the new instance being created. @@ -6416,11 +6441,11 @@ A ***copy constructor*** for a type `T` is a constructor having a single paramet > > the record class is immutable. The provided auto properties `Age` and `Name` are read-init. A copy constructor is provided, as is a primary constructor. *end example* -In certain circumstances ([§15.16.4.4](classes.md#151644-copy-and-clone-members)), a copy constructor may be provided by the compiler, and called by provided code. +In certain circumstances ([§15.16.6.4](classes.md#151664-copy-and-clone-members)), a copy constructor may be provided by the compiler, and called by provided code. A copy constructor on a type that has a required member list ([§15.7.1](classes.md#1571-general)) shall be decorated with SetsRequiredMembersAttribute ([§23.5.12.1](attributes.md#235121-the-setsrequiredmembers-attribute)). -#### 15.16.4.3 Equality members +#### 15.16.6.3 Equality members If a record class is derived directly from `object`, the record class type has a provided property declared as follows: @@ -6587,18 +6612,18 @@ The provided override of `GetHashCode()` returns an `int` result of combining th > > *end example* -#### 15.16.4.4 Copy and clone members +#### 15.16.6.4 Copy and clone members A record class type contains two copying members: -- A copy constructor ([§15.16.4.2](classes.md#151642-copy-constructors)) +- A copy constructor ([§15.16.6.2](classes.md#151662-copy-constructors)) - A provided public, parameter-less, instance clone method having an unspecified reserved name The copy constructor shall not execute any instance field/property initializers present in the record class declaration. If the constructor is not explicitly declared, it shall be provided by the implementation. If the provided record class is sealed, the constructor shall be private; otherwise; it shall be protected. An explicitly declared copy constructor shall be either public or protected, unless the record class is sealed. The first thing the constructor shall do, is to call a copy constructor of the base class, or a parameter-less `object` constructor if the record inherits from `object`. It is an error for a user-defined copy constructor to use an implicit or explicit *constructor_initializer* that doesn’t fulfill this requirement. After a base copy constructor is invoked, a provided copy constructor shall copy values for all instance fields implicitly or explicitly declared within the record class type. The sole presence of a copy constructor, whether explicit or implicit, shall not prevent an automatic addition of a default instance constructor. If a virtual clone method is present in the base record class, the provided clone method shall override it, and the return type of the clone method shall be the current containing type if the covariant-returns feature is supported, and the override return type otherwise. It is an error if the base record class clone method is sealed. If a virtual clone method is not present in the base record class, the return type of the clone method shall be the containing type and the method shall be virtual, unless the record class is sealed or abstract. If the containing record class is abstract, the provided clone method shall also be abstract. If the clone method is not abstract, it shall return the result of a call to a copy constructor. -#### 15.16.4.5 Printing members +#### 15.16.6.5 Printing members If a record class is derived directly from `object`, the class includes a provided method declared as follows: @@ -6768,17 +6793,17 @@ The provided method: > > *end example* -#### 15.16.4.6 Positional record class members +#### 15.16.6.6 Positional record class members -##### 15.16.4.6.1 General +##### 15.16.6.6.1 General As well as providing the members described in the preceding subclauses, positional record classes ([§15.2.1](classes.md#1521-general)) result in the implementation providing additional members with the same conditions as the other provided members, as described in the following subclauses. -##### 15.16.4.6.2 Primary constructor +##### 15.16.6.6.2 Primary constructor -The primary constructor of a record class is like that of a non-record class ([§15.11.6](classes.md#15116-primary-constructors)), with the following difference: Each parameter value is stored in a corresponding private instance field having a corresponding property with set and get accessors. +The primary constructor of a record class is like that of a non-record class (§prim-constructor), with the following difference: Each parameter value is stored in a corresponding private instance field having a corresponding property with set and get accessors. -##### 15.16.4.6.3 Properties +##### 15.16.6.6.3 Properties For each parameter of a *delimited_parameter_list* that has the same name and type as an explicitly declared instance field, the remainder of this subclause does not apply. @@ -6808,7 +6833,7 @@ For a record class: > > *end example* -##### 15.16.4.6.4 Deconstruct +##### 15.16.6.6.4 Deconstruct A positional record class ([§15.2.1](classes.md#1521-general)) with at least one parameter causes to be provided a public `void`-returning instance method called `Deconstruct` with an out parameter declaration for each parameter of the primary constructor declaration. Each parameter of `Deconstruct` has the same type as the corresponding parameter of the primary constructor declaration. The body of the method assigns to each parameter of `Deconstruct` the value from an instance member access to a member of the same name. The method may be declared explicitly. It is an error if the explicit declaration does not match the expected signature or accessibility, or is static. @@ -6838,11 +6863,11 @@ A positional record class ([§15.2.1](classes.md#1521-general)) with at least on > > *end example* -## 15.17 Declaring a collection type +## §declaring-a-collection-type Declaring a collection type -### 15.17.1 General +### §declaring-a-collection-type-general General -There are a number of contexts in which a collection expression ([§12.8.25](expressions.md#12825-collection-expressions)) may be converted to a collection type ([§10.2.22](conversions.md#10222-implicit-collection-expression-conversions)). One of them is for a target class, struct, or interface type to be made a collection type by annotating it with an attribute, as shown below. +There are a number of contexts in which a collection expression (§collection-expressions) may be converted to a collection type (§imp-collection-expression-conv). One of them is for a target class, struct, or interface type to be made a collection type by annotating it with an attribute, as shown below. Here is a simple user-defined collection type and its associated builder type: @@ -6887,7 +6912,7 @@ internal static class MyCollectionBuilder } ``` -The collection type shall be annotated with `CollectionBuilderAttribute` ([§23.5.13](attributes.md#23513-the-collectionbuilder-attribute)) that designates an associated, non-generic builder class or struct type having a collection-creation method (whose name is user-defined; in this case, it is `Create`). +The collection type shall be annotated with `CollectionBuilderAttribute` (§collection-builder-attr) that designates an associated, non-generic builder class or struct type having a collection-creation method (whose name is user-defined; in this case, it is `Create`). The job of a ***collection-creation method*** is to create and initialize an instance of its associated collection type. @@ -6913,9 +6938,9 @@ For a *collection_expression* with a target type `C` where the The span parameter for the collection-creation method may be explicitly marked `scoped` or `[UnscopedRef] ([§9.7.3](variables.md#973-the-scoped-modifier))`. If the parameter is implicitly or explicitly `scoped`, the compiler may allocate the storage for the span on the stack rather than the heap. -The construction of an instance of a collection type is described in [§15.17.2](classes.md#15172-collection-construction). +The construction of an instance of a collection type is described in §collection-construction. -### 15.17.2 Collection construction +### §collection-construction Collection construction The *collection_element*s of a *collection_expression* are evaluated in order, left to right. Each *collection_element* is evaluated exactly once, and any further references to the any elements refer to the results of this initial evaluation. @@ -6925,7 +6950,7 @@ An unhandled exception thrown from any of the methods used during construction s `Length`, `Count`, and `GetEnumerator` are assumed to have no side effects. -If the target type is a struct or class type that implements `System.Collections.IEnumerable`, and the target type does not have a collection-creation method ([§15.17.1](classes.md#15171-general)), the construction of the collection instance steps are, as follows: +If the target type is a struct or class type that implements `System.Collections.IEnumerable`, and the target type does not have a collection-creation method (§declaring-a-collection-type-general), the construction of the collection instance steps are, as follows: - The elements are evaluated in order. Some or all elements may be evaluated during the steps below rather than before. - The compiler may determine the known length of the collection expression by invoking countable properties ([§18.1](ranges.md#181-general)) or equivalent properties from well-known interfaces or types, on each *spread_element*’s *expression*. @@ -6989,7 +7014,7 @@ If the target type is an array, a `Span` or `ReadOnlySpan`, a type with a collec > > *end note* -## 15.18 Record class and non-record class differences +## 15.17 Record class and non-record class differences A record class differs from a non-record class in several important ways: diff --git a/standard/conversions.md b/standard/conversions.md index bbb260f3f..771cfe457 100644 --- a/standard/conversions.md +++ b/standard/conversions.md @@ -460,13 +460,13 @@ Although an implicit conversion to `object` is permitted, a warning shall be iss > > *end example* -### 10.2.22 Implicit collection expression conversions +### §imp-collection-expression-conv Implicit collection expression conversions An implicit collection expression conversion exists from a collection expression to the following types: - A single-dimensional array type `T[]`, in which case, the element type is `T`. - `System.Span` and `System.ReadOnlySpan`, in which cases, the element type is `T`. -- A type with an appropriate collection-creation method ([§15.17.1](classes.md#15171-general)), in which case, the element type is the iteration type ([§13.9.5](statements.md#1395-the-foreach-statement)) determined from a `GetEnumerator` instance method or enumerable interface, not from an extension method. +- A type with an appropriate collection-creation method (§declaring-a-collection-type-general), in which case, the element type is the iteration type ([§13.9.5](statements.md#1395-the-foreach-statement)) determined from a `GetEnumerator` instance method or enumerable interface, not from an extension method. - A struct or class type that implements `System.Collections.IEnumerable` where: - The type has an applicable ([§12.6.4.2](expressions.md#12642-applicable-function-member)) constructor that can be invoked with no arguments, and the constructor is accessible at the location of the collection expression. @@ -504,17 +504,17 @@ The following additional implicit conversions exist from a collection expression - To an interface type `I` where there is a collection-creation method associated with `I` that returns a type `V` and there is an implicit boxing conversion from `V` to `I`. The conversion is a collection expression conversion to `V` followed by an implicit boxing conversion from `V` to `I`. -When a collection expression is converted to a ref struct type, all ref safety requirements ([§9.7.2](variables.md#972-ref-safe-contexts), [§16.8.15](structs.md#16815-safe-context-constraint)) shall be met. +When a collection expression is converted to a ref struct type, all ref safety requirements ([§9.7.2](variables.md#972-ref-safe-contexts), [§16.6.15](structs.md#16615-safe-context-constraint)) shall be met. -### 10.2.23 Implicit inline array conversions +### §ImplicitInlineArrayConversions Implicit inline array conversions -The implicit inline array ([§16.6](structs.md#166-inline-arrays)) conversions are: +The implicit inline array (§InlineArray) conversions are: - From an expression designating a writable inline array with element type `T` to `System.Span` - From an expression designating a writable inline array with element type `T` to `System.ReadonlySpan` - From an expression designating a readonly inline array with element type `T` to `System.ReadonlySpan` -The conversion of an inline array to a `System.Span` or `System.ReadonlySpan` ignores any declared operators in the inline array type that might otherwise appear to be applicable. See [§16.6](structs.md#166-inline-arrays) for more information. +The conversion of an inline array to a `System.Span` or `System.ReadonlySpan` ignores any declared operators in the inline array type that might otherwise appear to be applicable. See §InlineArray for more information. ## 10.3 Explicit conversions @@ -760,7 +760,7 @@ The following implicit conversions are classified as standard implicit conversio - Boxing conversions ([§10.2.9](conversions.md#1029-boxing-conversions)) - Implicit constant expression conversions ([§10.2.11](conversions.md#10211-implicit-constant-expression-conversions)) - Implicit conversions involving type parameters ([§10.2.12](conversions.md#10212-implicit-conversions-involving-type-parameters)) -- Implicit inline array conversions ([§10.2.23](conversions.md#10223-implicit-inline-array-conversions)) +- Implicit inline array conversions (§ImplicitInlineArrayConversions) The standard implicit conversions specifically exclude user-defined implicit conversions. diff --git a/standard/delegates.md b/standard/delegates.md index 6389edb44..5e658893b 100644 --- a/standard/delegates.md +++ b/standard/delegates.md @@ -155,7 +155,7 @@ This definition of compatibility allows covariance in return type and contravari -> *Note*: The intuitive meaning of delegate compatibility is that a method is compatible with a delegate type if every invocation of the delegate could be replaced with an invocation of the method without violating type safety, treating optional parameters and parameter arrays as explicit parameters. For example, in the following code: +> *Note*: The intuitive meaning of delegate compatibility is that a method is compatible with a delegate type if every invocation of the delegate could be replaced with an invocation of the method without violating type safety, treating optional parameters and parameter collections as explicit parameters. For example, in the following code: > > > ```csharp diff --git a/standard/expressions.md b/standard/expressions.md index 8799cc6e3..805c8ed33 100644 --- a/standard/expressions.md +++ b/standard/expressions.md @@ -553,7 +553,7 @@ Every function member and delegate invocation includes an argument list, which p - For events, the argument list consists of the expression specified as the right operand of the `+=` or `-=` operator. - For user-defined operators, the argument list consists of the single operand of the unary operator or the two operands of the binary operator. -The arguments of properties ([§15.7](classes.md#157-properties)) and events ([§15.8](classes.md#158-events)) are always passed as value parameters ([§15.6.2.2](classes.md#15622-value-parameters)). The arguments of user-defined operators ([§15.10](classes.md#1510-operators)) are always passed as value parameters ([§15.6.2.2](classes.md#15622-value-parameters)) or input parameters ([§9.2.8](variables.md#928-input-parameters)). The arguments of indexers ([§15.9](classes.md#159-indexers)) are always passed as value parameters ([§15.6.2.2](classes.md#15622-value-parameters)), input parameters ([§9.2.8](variables.md#928-input-parameters)), reference parameters of kind `ref readonly` ([§15.6.2.3.3](classes.md#156233-reference-parameters)), or parameter arrays ([§15.6.2.4](classes.md#15624-parameter-arrays)). Output and reference parameters of kind `ref` are not supported for these categories of function members. +The arguments of properties ([§15.7](classes.md#157-properties)) and events ([§15.8](classes.md#158-events)) are always passed as value parameters ([§15.6.2.2](classes.md#15622-value-parameters)). The arguments of user-defined operators ([§15.10](classes.md#1510-operators)) are always passed as value parameters ([§15.6.2.2](classes.md#15622-value-parameters)) or input parameters ([§9.2.8](variables.md#928-input-parameters)). The arguments of indexers ([§15.9](classes.md#159-indexers)) are always passed as value parameters ([§15.6.2.2](classes.md#15622-value-parameters)), input parameters ([§9.2.8](variables.md#928-input-parameters)), reference parameters of kind `ref readonly` ([§15.6.2.3.3](classes.md#156233-reference-parameters)), or parameter collections ([§15.6.2.4](classes.md#15624-parameter-collections)). Output and reference parameters of kind `ref` are not supported for these categories of function members. The arguments of an instance constructor, method, indexer, or delegate invocation are specified as an *argument_list*: @@ -607,14 +607,14 @@ The position of an argument or parameter is defined as the number of arguments o The corresponding parameters for function member arguments are established as follows: - Arguments in the *argument_list* of instance constructors, methods, indexers and delegates: - - A positional argument where a parameter occurs at the same position in the parameter list corresponds to that parameter, unless the parameter is a parameter array and the function member is invoked in its expanded form. - - A positional argument of a function member with a parameter array invoked in its expanded form, which occurs at or after the position of the parameter array in the parameter list, corresponds to an element in the parameter array. + - A positional argument where a parameter occurs at the same position in the parameter list corresponds to that parameter, unless the parameter is a parameter collection and the function member is invoked in its expanded form. + - A positional argument of a function member with a parameter collection invoked in its expanded form, which occurs at or after the position of the parameter collection in the parameter list, corresponds to an element in the parameter collection. - A named argument corresponds to the parameter of the same name in the parameter list. - For indexers, when invoking the set or init accessor, the expression specified as the right operand of the assignment operator corresponds to the implicit `value` parameter of the set or init accessor declaration. - For properties, when invoking the get accessor there are no arguments. When invoking the set or init accessor, the expression specified as the right operand of the assignment operator corresponds to the implicit value parameter of the set or init accessor declaration. - For user-defined unary operators (including conversions), the single operand corresponds to the single parameter of the operator declaration. - For user-defined binary operators, the left operand corresponds to the first parameter, and the right operand corresponds to the second parameter of the operator declaration. -- An unnamed argument corresponds to no parameter when it is after an out-of-position named argument or a named argument that corresponds to a parameter array. +- An unnamed argument corresponds to no parameter when it is after an out-of-position named argument or a named argument that corresponds to a parameter collection. > *Note*: This prevents `void M(bool a = true, bool b = true, bool c = true);` being invoked by `M(c: false, valueB);`. The first argument is used out-of-position (the argument is used in first position, but the parameter named `c` is in third position), so the following arguments should be named. In other words, non-trailing named arguments are only allowed when the name and the position result in finding the same corresponding parameter. *end note* #### 12.6.2.3 Run-time evaluation of argument lists @@ -667,10 +667,10 @@ During the run-time processing of a function member invocation ([§12.6.6](expre > > *end example* -Methods, indexers, and instance constructors may declare their right-most parameter to be a parameter array ([§15.6.2.4](classes.md#15624-parameter-arrays)). Such function members are invoked either in their normal form or in their expanded form depending on which is applicable ([§12.6.4.2](expressions.md#12642-applicable-function-member)): +Methods, indexers, and instance constructors may declare their right-most parameter to be a parameter collection ([§15.6.2.4](classes.md#15624-parameter-collections)). Such function members are invoked either in their normal form or in their expanded form depending on which is applicable ([§12.6.4.2](expressions.md#12642-applicable-function-member)): -- When a function member with a parameter array is invoked in its normal form, the argument given for the parameter array shall be a single expression that is implicitly convertible ([§10.2](conversions.md#102-implicit-conversions)) to the parameter array type. In this case, the parameter array acts precisely like a value parameter. -- When a function member with a parameter array is invoked in its expanded form, the invocation shall specify zero or more positional arguments for the parameter array, where each argument is an expression that is implicitly convertible ([§10.2](conversions.md#102-implicit-conversions)) to the element type of the parameter array. In this case, the invocation creates an instance of the parameter array type with a length corresponding to the number of arguments, initializes the elements of the array instance with the given argument values, and uses the newly created array instance as the actual argument. +- When a function member with a parameter collection is invoked in its normal form, the argument given for the parameter collection shall be a single expression that is implicitly convertible ([§10.2](conversions.md#102-implicit-conversions)) to the parameter collection type. In this case, the parameter collection acts precisely like a value parameter. +- When a function member with a parameter collection is invoked in its expanded form, the invocation shall specify zero or more positional arguments for the parameter collection, where each argument is an expression that is implicitly convertible ([§10.2](conversions.md#102-implicit-conversions)) to the element type of the parameter collection. In this case, the invocation creates an instance of the parameter collection type with a length corresponding to the number of arguments, initializes the elements of the array instance with the given argument values, and uses the newly created array instance as the actual argument. The expressions of an argument list are always evaluated in textual order. @@ -701,7 +701,7 @@ The expressions of an argument list are always evaluated in textual order. > > *end example* -When a function member with a parameter array is invoked in its expanded form with at least one expanded argument, the invocation is processed as if an array creation expression with an array initializer ([§12.8.17.4](expressions.md#128174-array-creation-expressions)) was inserted around the expanded arguments. An empty array is passed when there are no arguments for the parameter array; it is unspecified whether the reference passed is to a newly allocated or existing empty array. +When a function member with a parameter collection is invoked in its expanded form with at least one expanded argument, the invocation is processed as if the expanded arguments were the *collection_element*s of a *collection_expression* (§collection-expressions). An empty collection is passed when there are no arguments for the parameter collection; it is unspecified whether the reference passed is to a newly allocated or existing empty collection. > *Example*: Given the declaration > @@ -1077,20 +1077,20 @@ A function member is said to be an ***applicable function member*** with respect - Each argument in `A` corresponds to a parameter in the function member declaration as described in [§12.6.2.2](expressions.md#12622-corresponding-parameters), at most one argument corresponds to each parameter, and any parameter to which no argument corresponds is an optional parameter. - For each argument in `A`, the parameter-passing mode of the argument is identical to the parameter-passing mode of the corresponding parameter, and - - for a value parameter or a parameter array, an implicit conversion ([§10.2](conversions.md#102-implicit-conversions)) exists from the argument expression to the type of the corresponding parameter, or + - for a value parameter or a parameter collection, an implicit conversion ([§10.2](conversions.md#102-implicit-conversions)) exists from the argument expression to the type of the corresponding parameter, or - for a reference parameter whose type is a struct type, an implicit interpolated string handler conversion exists from the argument to the type of the corresponding parameter, or - for a reference or output parameter, there is an identity conversion between the type of the argument expression (if any) and the type of the corresponding parameter, or - for an input parameter when the corresponding argument has the `in` modifier, there is an identity conversion between the type of the argument expression (if any) and the type of the corresponding parameter, or - for an input parameter when the corresponding argument omits the `in` modifier, an implicit conversion ([§10.2](conversions.md#102-implicit-conversions)) exists from the argument expression to the type of the corresponding parameter. - for a `ref readonly` parameter when the corresponding argument omits the `ref` modifier, an implicit conversion ([§10.2](conversions.md#102-implicit-conversions)) exists from the argument expression to the type of the corresponding parameter. -For a function member that includes a parameter array, if the function member is applicable by the above rules, it is said to be applicable in its ***normal form***. If a function member that includes a parameter array is not applicable in its normal form, the function member might instead be applicable in its ***expanded form***: +For a function member that includes a parameter collection, if the function member is applicable by the above rules, it is said to be applicable in its ***normal form***. If a function member that includes a parameter collection is not applicable in its normal form, the function member might instead be applicable in its ***expanded form***: -- The expanded form is constructed by replacing the parameter array in the function member declaration with zero or more value parameters of the element type of the parameter array such that the number of arguments in the argument list `A` matches the total number of parameters. If `A` has fewer arguments than the number of fixed parameters in the function member declaration, the expanded form of the function member cannot be constructed and is thus not applicable. +- The expanded form is constructed by replacing the parameter collection in the function member declaration with zero or more value parameters of the collection's element type such that the number of arguments in the argument list `A` matches the total number of parameters. If `A` has fewer arguments than the number of fixed parameters in the function member declaration, the expanded form of the function member cannot be constructed and is thus not applicable. - Otherwise, the expanded form is applicable if for each argument in `A`, one of the following is true: - the parameter-passing mode of the argument is identical to the parameter-passing mode of the corresponding parameter, and: - for a fixed value parameter or a value parameter created by the expansion, an implicit conversion ([§10.2](conversions.md#102-implicit-conversions)) exists from the argument expression to the type of the corresponding parameter; or - - for a by-reference parameter, the type of the argument expression is identical to the type of the corresponding parameter. + - for an `in`, `out`, or `ref` parameter, the type of the argument expression is identical to the type of the corresponding parameter. - the parameter-passing mode of the argument is value, and the parameter-passing mode of the corresponding parameter is input or `ref readonly`, and an implicit conversion ([§10.2](conversions.md#102-implicit-conversions)) exists from the argument expression to the type of the corresponding parameter. When the implicit conversion from the argument type to the parameter type of an input parameter is a dynamic implicit conversion ([§10.2.10](conversions.md#10210-implicit-dynamic-conversions)), the results are undefined. @@ -1138,27 +1138,32 @@ Parameter lists for each of the candidate function members are constructed in th - Reference and output parameters are removed from the parameter list - The parameters are reordered so that they occur at the same position as the corresponding argument in the argument list. -Given an argument list `A` with a set of argument expressions `{E₁, E₂, ..., Eᵥ}` and two applicable function members `Mᵥ` and `Mₓ` with parameter types `{P₁, P₂, ..., Pᵥ}` and `{Q₁, Q₂, ..., Qᵥ}`, `Mᵥ` is defined to be a ***better function member*** than `Mₓ` if +Given an argument list `A` with a set of argument expressions `{E₁, E₂, …, Eᵥ}` and two applicable function members `Mᵥ` and `Mₓ` with parameter types `{P₁, P₂, …, Pᵥ}` and `{Q₁, Q₂, …, Qᵥ}`, `Mᵥ` is defined to be a ***better function member*** than `Mₓ` if - for each argument, the implicit conversion from `Eᵥ` to `Pᵥ` is not an anonymous function type conversion, and - - `Mᵥ` is a non-generic method or `Mᵥ` is a generic method with type parameters `{X₁, X₂, ..., Xᵥ}` and for each type parameter the type argument is inferred from an expression or from a type other than an anonymous function type, and - - for at least one argument, the implicit conversion from `Eᵥ` to `Qᵥ` is an anonymous function type conversion, or `Mₓ` is a generic method with type parameters `{Y₁, Y₂, ..., Yᵥ}` and for at least one type parameter the type argument is inferred from an anonymous function type, or + - `Mᵥ` is a non-generic method or `Mᵥ` is a generic method with type parameters `{X₁, X₂, …, Xᵥ}` and for each type parameter the type argument is inferred from an expression or from a type other than an anonymous function type, and + - for at least one argument, the implicit conversion from `Eᵥ` to `Qᵥ` is an anonymous function type conversion, or `Mₓ` is a generic method with type parameters `{Y₁, Y₂, …, Yᵥ}` and for at least one type parameter the type argument is inferred from an anonymous function type, or -- for each argument, the implicit conversion from `Eᵥ` to `Qᵥ` is not better than the implicit conversion from `Eᵥ` to `Pᵥ`, and for at least one argument, the conversion from `Eᵥ` to `Pᵥ` is better than the conversion from `Eᵥ` to `Qᵥ`. +- for each argument, the implicit conversion from `Eᵥ` to `Qᵥ` is not better than the implicit conversion from `Eᵥ` to `Pᵥ`, and +- for at least one argument, the conversion from `Eᵥ` to `Pᵥ` is better than the conversion from `Eᵥ` to `Qᵥ`. -In case the parameter type sequences `{P₁, P₂, ..., Pᵥ}` and `{Q₁, Q₂, ..., Qᵥ}` are equivalent (i.e., each `Pᵢ` has an identity conversion to the corresponding `Qᵢ`), the following tie-breaking rules are applied, in order, to determine the better function member. +In case the parameter type sequences `{P₁, P₂, …, Pᵥ}` and `{Q₁, Q₂, …, Qᵥ}` are equivalent (i.e., each `Pᵢ` has an identity conversion to the corresponding `Qᵢ`), the following tie-breaking rules are applied, in order, to determine the better function member. - If `Mᵢ` is a non-generic method and `Mₑ` is a generic method, then `Mᵢ` is better than `Mₑ`. -- Otherwise, if `Mᵢ` is applicable in its normal form and `Mₑ` has a params array and is applicable only in its expanded form, then `Mᵢ` is better than `Mₑ`. -- Otherwise, if both methods have params arrays and are applicable only in their expanded forms, and if the params array of `Mᵢ` has fewer elements than the params array of `Mₑ`, then `Mᵢ` is better than `Mₑ`. -- Otherwise, if `Mᵥ` has more specific parameter types than `Mₓ`, then `Mᵥ` is better than `Mₓ`. Let `{R1, R2, ..., Rn}` and `{S1, S2, ..., Sn}` represent the uninstantiated and unexpanded parameter types of `Mᵥ` and `Mₓ`. `Mᵥ`’s parameter types are more specific than `Mₓ`s if, for each parameter, `Rx` is not less specific than `Sx`, and, for at least one parameter, `Rx` is more specific than `Sx`: +- Otherwise, if `Mᵢ` is applicable in its normal form and `Mₑ` has a parameter collection and is applicable only in its expanded form, then `Mᵢ` is better than `Mₑ`. +- Otherwise, if both methods have parameter collections and are applicable only in their expanded forms, and if the parameter collection of `Mᵢ` has fewer elements than the parameter collection of `Mₑ`, then `Mᵢ` is better than `Mₑ`. +- Otherwise, if `Mᵥ` has more specific parameter types than `Mₓ`, then `Mᵥ` is better than `Mₓ`. Let `{R1, R2, …, Rn}` and `{S1, S2, …, Sn}` represent the uninstantiated and unexpanded parameter types of `Mᵥ` and `Mₓ`. `Mᵥ`’s parameter types are more specific than `Mₓ`s if, for each parameter, `Rx` is not less specific than `Sx`, and, for at least one parameter, `Rx` is more specific than `Sx`: - A type parameter is less specific than a non-type parameter. - Recursively, a constructed type is more specific than another constructed type (with the same number of type arguments) if at least one type argument is more specific and no type argument is less specific than the corresponding type argument in the other. - An array type is more specific than another array type (with the same number of dimensions) if the element type of the first is more specific than the element type of the second. - Otherwise if one member is a non-lifted operator and the other is a lifted operator, the non-lifted one is better. - If neither function member was found to be better, and all parameters of `Mᵥ` have a corresponding argument whereas default arguments need to be substituted for at least one optional parameter in `Mₓ`, then `Mᵥ` is better than `Mₓ`. - If for at least one parameter `Mᵥ` uses the ***better parameter-passing choice*** ([§12.6.4.4](expressions.md#12644-better-parameter-passing-mode)) than the corresponding parameter in `Mₓ` and none of the parameters in `Mₓ` use the better parameter-passing choice than `Mᵥ`, `Mᵥ` is better than `Mₓ`. +- Otherwise, if both methods have parameter collections and are applicable only in their expanded forms then `Mᵢ` is better than `Mₑ` if the same set of arguments corresponds to the collection elements for both methods, and one of the following holds: + - both parameter collections are not *span_type*s, and an implicit conversion exists from the parameter collection of `Mᵢ` to the parameter collection of `Mₑ` + - the parameter collection of `Mᵢ` is `System.ReadOnlySpan`, and the parameter collection of `Mₑ` is `System.Span`, and an identity conversion exists from `Eᵢ` to `Eₑ` + - the parameter collection of `Mᵢ` is `System.ReadOnlySpan` or `System.Span`, and the parameter collection of `Mₑ` is an array or array interface type with element type `Eₑ`, and an identity conversion exists from `Eᵢ` to `Eₑ` - Otherwise, no function member is better. A `delegate*` is more specific than `void*`. @@ -1300,7 +1305,7 @@ Even though overload resolution of a dynamically bound operation takes place at - For a delegate invocation ([§12.8.10.4](expressions.md#128104-delegate-invocations)), the list is a single function member with the same parameter list as the *delegate_type* of the invocation - For a method invocation ([§12.8.10.2](expressions.md#128102-method-invocations)) on a type, or on a value whose static type is not dynamic, the set of accessible methods in the method group is known at compile-time. - For an object creation expression ([§12.8.17.2](expressions.md#128172-object-creation-expressions)) the set of accessible constructors in the type is known at compile-time. -- For an indexer access ([§12.8.12.5](expressions.md#128125-indexer-access)) the set of accessible indexers in the receiver is known at compile-time. +- For an indexer access ([§12.8.12.4](expressions.md#128124-indexer-access)) the set of accessible indexers in the receiver is known at compile-time. In these cases a limited compile-time check is performed on each member in the known set of function members, to see if it can be known for certain never to be invoked at run-time. For each function member `F` a modified parameter and argument list are constructed: @@ -1335,7 +1340,7 @@ The run-time processing of a function member invocation consists of the followin - `M` is invoked. - Otherwise, if the type of `E` is a value-type `V`, and `M` is declared or overridden in `V`: - `E` is evaluated. If this evaluation causes an exception, then no further steps are executed. For an instance constructor, this evaluation consists of allocating storage (typically from an execution stack) for the new object. In this case `E` is classified as a variable. - - If `E` is not classified as a variable, or if `V` is not a readonly struct type ([§16.2.2](structs.md#1622-struct-modifiers)) and `M` is not a readonly function member ([§16.8.12](structs.md#16812-methods)), and `E` is one of: + - If `E` is not classified as a variable, or if `V` is not a readonly struct type ([§16.2.2](structs.md#1622-struct-modifiers)) and `M` is not a readonly function member ([§16.6.12](structs.md#16612-methods)), and `E` is one of: - an input parameter ([§15.6.2.3.2](classes.md#156232-input-parameters)), or - a `readonly` field ([§15.5.3](classes.md#1553-readonly-fields)), or - a `readonly` reference variable or return ([§9.7](variables.md#97-reference-variables-and-returns)), @@ -1378,12 +1383,12 @@ An expression `E`, with a type `S` other than `dynamic`, can be ***deconstructed - If `E` is a *tuple-literal* the result of deconstruction is the expression `E` itself. -- Otherwise, if `E` has a tuple type `(T₁, ..., Tₙ)`, then the result of deconstruction is semantically equivalent to the expression `(E.Item1, ..., E.Itemn)` except `E` is evaluated only once. +- Otherwise, if `E` has a tuple type `(T₁, …, Tₙ)`, then the result of deconstruction is semantically equivalent to the expression `(E.Item1, …, E.Itemn)` except `E` is evaluated only once. - Otherwise if there is a unique instance or extension method `S.Deconstruct`; with `n ≥ 2` output parameters, with types `T₁` to `Tₙ`, and no other parameters; then `E` can be deconstructed. The result of the deconstruction is semantically equivalent to replacing `E` with the following pseudo-code: >```csharp - > E.Deconstruct(out T1 v1, ..., out TN vn) andThen (v1, ..., vn); + > E.Deconstruct(out T1 v1, …, out TN vn) andThen (v1, …, vn); >``` Where `andThen` is a pseudo C# operation which performs its left-hand operand and then returns its right-operand as the result. @@ -1624,7 +1629,7 @@ fragment Interpolated_Raw_String_Character multi_line_interpolated_raw_string_expression : Interpolated_Raw_String_Start Whitespace* New_Line - (Interpolated_Raw_String_Mid | New_Line)* New_Line + (Interpolated_Raw_String_Mid | New_Line)* New_Line Whitespace* Interpolated_Raw_String_End ; ``` @@ -1953,7 +1958,7 @@ In a member access of the form `E.I`, if `E` is a single identifier, and if the > > *end example* -With respect to primary constructors ([§15.11.6](classes.md#15116-primary-constructors)), the rule above affects whether an identifier within an instance member should be treated as a type reference, or as a primary constructor parameter reference, which, in turn, captures the parameter into the state of the enclosing type. Even though "the member lookup of `E.I` is never ambiguous," when lookup yields a member group, in some cases it is impossible to determine whether a member access refers to a static member or an instance member without fully resolving (binding) the member access. At the same time, capturing a primary constructor parameter changes properties of enclosing type in a way that affects semantic analysis. For example, the type might become unmanaged and fail certain constraints because of that. There are even scenarios for which binding can succeed either way, depending on whether the parameter is considered captured or not. +With respect to primary constructors (§prim-constructor), the rule above affects whether an identifier within an instance member should be treated as a type reference, or as a primary constructor parameter reference, which, in turn, captures the parameter into the state of the enclosing type. Even though "the member lookup of `E.I` is never ambiguous," when lookup yields a member group, in some cases it is impossible to determine whether a member access refers to a static member or an instance member without fully resolving (binding) the member access. At the same time, capturing a primary constructor parameter changes properties of enclosing type in a way that affects semantic analysis. For example, the type might become unmanaged and fail certain constraints because of that. There are even scenarios for which binding can succeed either way, depending on whether the parameter is considered captured or not. An ambiguity error shall result for a member access `E.I` when all the following conditions are met: @@ -2042,7 +2047,7 @@ A *null_conditional_projection_initializer* is a restriction of *null_conditiona #### 12.8.9.1 General A null-forgiving expression’s value, type, classification ([§12.2](expressions.md#122-expression-classifications)) -and safe-context ([§16.8.15](structs.md#16815-safe-context-constraint)) is the value, type, classification and safe-context of its *primary_expression*. +and safe-context ([§16.6.15](structs.md#16615-safe-context-constraint)) is the value, type, classification and safe-context of its *primary_expression*. ```ANTLR null_forgiving_expression @@ -2469,7 +2474,7 @@ The *primary_expression* of an *element_access* shall not be an *array_creation_ An *element_access* is dynamically bound ([§12.3.3](expressions.md#1233-dynamic-binding)) if at least one of the following holds: - The *primary_expression* has compile-time type `dynamic`. -- At least one expression of the *argument_list* has compile-time type `dynamic`, and the *primary_no_array_creation_expression* does not have an inline array type ([§16.6](structs.md#166-inline-arrays)) or there is more than one *argument* in the *argument_list*. +- At least one expression of the *argument_list* has compile-time type `dynamic`, and the *primary_no_array_creation_expression* does not have an inline array type (§InlineArray) or there is more than one *argument* in the *argument_list*. In this case the compile-time type of the *element_access* depends on the compile-time type of its *primary_expression*: if it has an array type then the compile-time type is the element type of that array type; otherwise the compile-time type is `dynamic` and the *element_access* is classified as a value of type `dynamic`. The rules below to determine the meaning of the *element_access* are then applied at run-time, using the run-time type instead of the compile-time type of those of the *primary_expression* and *argument_list* expressions which have the compile-time type `dynamic`. If the *primary_expression* does not have compile-time type `dynamic`, then the element access undergoes a limited compile-time check as described in [§12.6.5](expressions.md#1265-compile-time-checking-of-dynamic-member-invocation). @@ -2485,15 +2490,15 @@ In this case the compile-time type of the *element_access* depends on the compil > > *end example* -If the *primary_expression* of an *element_access* is a value of an *array_type*, the *element_access* is an array access ([§12.8.12.2](expressions.md#128122-array-access)). Otherwise, if the *primary_no_array_creation_expression* of an *element_access* is a variable or value of an inline array type and the *argument_list* consists of a single argument, the *element_access* is an inline array element access ([§12.8.12.3](expressions.md#128123-inline-array-element-access)). Otherwise, the *primary_no_array_creation_expression* shall be a variable or value of a class, struct, or interface type that has one or more indexer members, in which case the *element_access* is an indexer access ([§12.8.12.5](expressions.md#128125-indexer-access)). +If the *primary_expression* of an *element_access* is a value of an *array_type*, the *element_access* is an array access ([§12.8.12.2](expressions.md#128122-array-access)). Otherwise, if the *primary_no_array_creation_expression* of an *element_access* is a variable or value of an inline array type and the *argument_list* consists of a single argument, the *element_access* is an inline array element access (§InlineArrayElementAccess). Otherwise, the *primary_no_array_creation_expression* shall be a variable or value of a class, struct, or interface type that has one or more indexer members, in which case the *element_access* is an indexer access ([§12.8.12.4](expressions.md#128124-indexer-access)). - a value of an array type, the *element_access* is an array access ([§12.8.12.2](expressions.md#128122-array-access)); -- a value of `string` type, the *element_access* is a string access ([§12.8.12.4](expressions.md#128124-string-access)); -- otherwise, the *primary_expression* shall be a variable or value of a class, struct, or interface type that has one or more indexer members, in which case the *element_access* is an indexer access ([§12.8.12.5](expressions.md#128125-indexer-access)). +- a value of `string` type, the *element_access* is a string access ([§12.8.12.3](expressions.md#128123-string-access)); +- otherwise, the *primary_expression* shall be a variable or value of a class, struct, or interface type that has one or more indexer members, in which case the *element_access* is an indexer access ([§12.8.12.4](expressions.md#128124-indexer-access)). #### 12.8.12.2 Array access -For access to elements in an inline array ([§16.6](structs.md#166-inline-arrays)) see [§12.8.12.3](expressions.md#128123-inline-array-element-access). +For access to elements in an inline array (§InlineArray) see §InlineArrayElementAccess. For an array access the *argument_list* shall not contain named arguments or by-reference arguments ([§15.6.2.3](classes.md#15623-by-reference-parameters)). @@ -2521,16 +2526,16 @@ The run-time processing of an array access of the form `P[A]`, where `P` is a *p -> > > *Note:* A range of elements of an array cannot be assigned to using an array access. This differs from indexer accesses ([§12.8.12.5](expressions.md#128125-indexer-access)) which may, but need not, support assignment to a range of indices specified by a `Range` value. *end note* +> > > *Note:* A range of elements of an array cannot be assigned to using an array access. This differs from indexer accesses ([§12.8.12.4](expressions.md#128124-indexer-access)) which may, but need not, support assignment to a range of indices specified by a `Range` value. *end note* - Otherwise: - The result of evaluating the array access is a variable reference ([§9.5](variables.md#95-variable-references)) of the element type of the array. - The value of each expression in the *argument_list* is checked against the actual bounds of each dimension of the array instance referenced by `P`. If one or more values are out of range, a `System.IndexOutOfRangeException` is thrown and no further steps are executed. - The variable reference of the array element given by the index expressions is computed, and this becomes the result of the array access. -#### 12.8.12.3 Inline array element access +#### §InlineArrayElementAccess Inline array element access -For access to an element in an inline array ([§16.6](structs.md#166-inline-arrays)), the *primary_no_array_creation_expression* of the *element_access* shall designate an inline array. Furthermore, the *argument_list* shall contain a single *argument*, which is not a named argument ([§12.6.2.1](expressions.md#12621-general)). That *argument* shall be of type `int`, or be implicitly convertible to type `int`, `System.Index`, or `System.Range`. +For access to an element in an inline array (§InlineArray), the *primary_no_array_creation_expression* of the *element_access* shall designate an inline array. Furthermore, the *argument_list* shall contain a single *argument*, which is not a named argument ([§12.6.2.1](expressions.md#12621-general)). That *argument* shall be of type `int`, or be implicitly convertible to type `int`, `System.Index`, or `System.Range`. It is a compile-time error if *argument* is a constant expression whose value results in an index outside the bounds of the inline array. If at runtime the value of *argument* results in an index outside the bounds of the inline array, a `System.IndexOutOfRangeException` is thrown. @@ -2616,7 +2621,7 @@ The value of *argument* is converted to `int` and the element access is interpre *argument* is converted to `System.Index` and then to an `int`-based index value indicating the element position relative to the start of the inline array. Then, the element access is interpreted as described when *argument*’s type is `int`. -Using an index of `System.Index` to access an element in a non-inline array is described in [§12.8.12.2](expressions.md#128122-array-access). However, note carefully that that process is *not* used when an inline array is indexed using a `System.Index`. Specifically, an inline array element access ignores any declared indexers in the inline array type. See [§16.6](structs.md#166-inline-arrays) for more information. +Using an index of `System.Index` to access an element in a non-inline array is described in [§12.8.12.2](expressions.md#128122-array-access). However, note carefully that that process is *not* used when an inline array is indexed using a `System.Index`. Specifically, an inline array element access ignores any declared indexers in the inline array type. See §InlineArray for more information. **When *argument*’s type is implicitly convertible to `System.Range`** @@ -2644,7 +2649,7 @@ passing the `int` equivalents of the Range’s start and end Indexes, respective static System.ReadOnlySpan GetSlice(in «InlineArrayType» array) ``` -Using an index of `System.Range` to access an element in a non-inline array is described in [§12.8.12.2](expressions.md#128122-array-access). However, note carefully that that process is *not* used when an inline array is indexed using a `System.Range`. Specifically, an inline array element access ignores any declared Slice methods in the inline array type. See [§16.6](structs.md#166-inline-arrays) for more information. +Using an index of `System.Range` to access an element in a non-inline array is described in [§12.8.12.2](expressions.md#128122-array-access). However, note carefully that that process is *not* used when an inline array is indexed using a `System.Range`. Specifically, an inline array element access ignores any declared Slice methods in the inline array type. See §InlineArray for more information. If *primary_no_array_creation_expression* is a value, an error is reported. @@ -2679,7 +2684,7 @@ If *primary_no_array_creation_expression* is a value, an error is reported. > > *end example* -#### 12.8.12.4 String access +#### 12.8.12.3 String access For a string access the *argument_list* of the *element_access* shall contain a single unnamed value argument ([§15.6.2.2](classes.md#15622-value-parameters)) which shall be: @@ -2707,7 +2712,7 @@ The run-time processing of a string access of the form `P[A]`, where `P` is a *p - The value of the converted index expression is checked against the actual bounds of the string instance referenced by `P`. If the value is out of range, a `System.IndexOutOfRangeException` is thrown and no further steps are executed. - The value of character at the offset of the converted index expression with the string `P` becomes the result of the string access. -#### 12.8.12.5 Indexer access +#### 12.8.12.4 Indexer access For an indexer access, the *primary_expression* of the *element_access* shall be a variable or value of a class, struct, or interface type, and this type shall implement one or more indexers that are applicable with respect to the *argument_list* of the *element_access*. The *argument_list* shall not contain `out` or `ref` arguments. @@ -3812,7 +3817,7 @@ When an instance of a struct `S` having a required member list ([§15.7.1](class A stack allocation expression allocates a block of memory from the execution stack. The ***execution stack*** is an area of memory where local variables are stored. The execution stack is not part of the managed heap. The memory used for local variable storage is automatically recovered when the current function returns. -The safe context rules for a stack allocation expression are described in [§16.8.15.10](structs.md#1681510-stackalloc). +The safe context rules for a stack allocation expression are described in [§16.6.15.10](structs.md#1661510-stackalloc). ```ANTLR stackalloc_expression @@ -3982,7 +3987,7 @@ These are the same transformations applied in [§6.4.3](lexical-structure.md#643 An *anonymous_method_expression* is one of two ways of defining an anonymous function. These are further described in [§12.22](expressions.md#1222-anonymous-function-expressions). -### 12.8.25 Collection expressions +### §collection-expressions Collection expressions A ***collection expression*** is a `[]`-delimited, comma-separated set of zero or more *collection_element*s that together represent a collection. @@ -4005,7 +4010,7 @@ spread_element ; ``` -On its own, a *collection_expression* has no type, but, rather, it is target-typed; that is, depending on the context in which it is used, it is converted ([§10.2.22](conversions.md#10222-implicit-collection-expression-conversions)) to the type of the target (presuming such a conversion is permitted). Any type that supports a *collection_initializer* ([§12.8.17.2.3](expressions.md#1281723-collection-initializers)) may be a target type for a *collection_expression*. A type designated with `CollectionBuilderAttribute` may also be a target type ([§15.17.1](classes.md#15171-general)). +On its own, a *collection_expression* has no type, but, rather, it is target-typed; that is, depending on the context in which it is used, it is converted (§imp-collection-expression-conv) to the type of the target (presuming such a conversion is permitted). Any type that supports a *collection_initializer* ([§12.8.17.2.3](expressions.md#1281723-collection-initializers)) may be a target type for a *collection_expression*. A type designated with `CollectionBuilderAttribute` may also be a target type (§declaring-a-collection-type-general). The *expression* of a *collection_element* need not be a constant. A *collection_expression* is not a compile-time constant, even if all its *collection_element*s are. @@ -4345,7 +4350,7 @@ All non-positional properties being changed shall have both set and init accesso This expression is evaluated as follows: -- For a record class type, the receiver’s clone method ([§15.16.4.4](classes.md#151644-copy-and-clone-members)) is invoked, and its result is converted to the receiver’s type. +- For a record class type, the receiver’s clone method ([§15.16.6.4](classes.md#151664-copy-and-clone-members)) is invoked, and its result is converted to the receiver’s type. - For a record struct or non-record struct type, the receiver is copied. - Each `member_initializer` is processed the same way as an assignment to a field or property access of the result of the conversion. Assignments are processed in lexical order. If *member_initializer_list* is omitted, no members are changed. @@ -5926,7 +5931,7 @@ A non-`static` local function or non-`static` anonymous function can capture sta A *lambda_expression* shall not contain any *parameter_modifier*s with the `this` modifier. -An *anonymous_method_expression* shall not contain any *default_argument*s or *parameter_array*s. +An *anonymous_method_expression* shall not contain any *default_argument*s or *parameter_collection*s. When recognising an *anonymous_function_body* if both the *null_conditional_invocation_expression* and *expression* alternatives are applicable then the former shall be chosen. @@ -6008,7 +6013,7 @@ The behavior of *lambda_expression*s and *anonymous_method_expression*s is the s - Only *lambda_expression*s have conversions to compatible expression tree types ([§8.6](types.md#86-expression-tree-types)). - Only *lambda_expression* parameters may contain ‘scoped’. - Only *lambda_expression*s may have *attributes* and explicit return types. -- An *anonymous_method_expression* may not contain any *default_argument*s or *parameter_array*s. +- An *anonymous_method_expression* may not contain any *default_argument*s or *parameter_collection*s. The contextual keyword `var` shall not be used as an explicit return type in a *lambda_expression*. @@ -6138,7 +6143,7 @@ An anonymous function cannot be a receiver, argument, or operand of a dynamicall #### 12.22.6.1 General -Any local variable, value parameter, or parameter array whose scope includes the *lambda_expression* or *anonymous_method_expression* is called an ***outer variable*** of the anonymous function. In an instance function member of a class, the `this` value is considered a value parameter and is an outer variable of any anonymous function contained within the function member. +Any local variable, value parameter, or parameter collection whose scope includes the *lambda_expression* or *anonymous_method_expression* is called an ***outer variable*** of the anonymous function. In an instance function member of a class, the `this` value is considered a value parameter and is an outer variable of any anonymous function contained within the function member. If the modifier `static` is present, the anonymous function cannot capture state from the enclosing scope. As a result, locals, parameters, and `this` from the enclosing scope are not available to that anonymous function. diff --git a/standard/grammar.md b/standard/grammar.md index f7a678bc5..2504fb8e2 100644 --- a/standard/grammar.md +++ b/standard/grammar.md @@ -995,7 +995,6 @@ primary_expression | pointer_member_access // unsafe code support | pointer_element_access // unsafe code support | stackalloc_expression - | collection_expression ; // Source: §12.8.3 Interpolated string expressions @@ -1166,7 +1165,7 @@ fragment Interpolated_Raw_String_Character multi_line_interpolated_raw_string_expression : Interpolated_Raw_String_Start Whitespace* New_Line - (Interpolated_Raw_String_Mid | New_Line)* New_Line + (Interpolated_Raw_String_Mid | New_Line)* New_Line Whitespace* Interpolated_Raw_String_End ; @@ -1453,24 +1452,6 @@ named_entity_target | qualified_alias_member ; -// Source: §12.8.25 Collection expressions -collection_expression - : '[' (collection_element (',' collection_element)*)? ']' - ; - -collection_element - : expression_element - | spread_element - ; - -expression_element - : expression - ; - -spread_element - : '..' expression - ; - // Source: §12.9.1 General unary_expression : primary_expression @@ -1655,7 +1636,22 @@ anonymous_function_signature ; explicit_anonymous_function_signature - : '(' parameter_list? ')' + : '(' explicit_anonymous_function_parameter_list? ')' + ; + +explicit_anonymous_function_parameter_list + : explicit_anonymous_function_parameter + (',' explicit_anonymous_function_parameter)* + ; + +explicit_anonymous_function_parameter + : attributes? 'scoped'? anonymous_function_parameter_modifier? type identifier + ; + +anonymous_function_parameter_modifier + : 'ref' + | 'out' + | 'in' ; implicit_anonymous_function_signature @@ -2273,7 +2269,7 @@ using_directive // Source: §14.6.2 Using alias directives using_alias_directive - : 'using' 'unsafe'? identifier '=' (namespace_name | type) ';' + : 'using' identifier '=' namespace_or_type_name ';' ; // Source: §14.6.3 Using namespace directives @@ -2283,7 +2279,7 @@ using_namespace_directive // Source: §14.6.4 Using static directives using_static_directive - : 'using' 'static' 'unsafe'? type_name ';' + : 'using' 'static' type_name ';' ; // Source: §14.7 Namespace member declarations @@ -2313,20 +2309,9 @@ class_declaration ; non_record_class_declaration - : non_record_class_without_positional_members - | non_record_class_with_positional_members - ; - -non_record_class_without_positional_members - : attributes? class_modifier* 'partial'? 'class' identifier - type_parameter_list? class_base? - type_parameter_constraints_clause* class_body - ; - -non_record_class_with_positional_members : attributes? class_modifier* 'partial'? 'class' identifier - type_parameter_list? delimited_parameter_list class_base? - type_parameter_constraints_clause* class_body + type_parameter_list? class_base? type_parameter_constraints_clause* + class_body ; // Source: §15.2.2.1 General @@ -2359,10 +2344,6 @@ class_base | ':' class_type base_argument_list? ',' interface_type_list ; -base_argument_list - : '(' argument_list? ')' - ; - interface_type_list : interface_type (',' interface_type)* ; @@ -2403,7 +2384,6 @@ constructor_constraint // Source: §15.2.6 Class body class_body : '{' class_member_declaration* '}' ';'? - | ';' ; // Source: §15.3.1 General @@ -2565,7 +2545,7 @@ parameter_modifier ; parameter_mode_modifier - : ref_kind + : 'ref' | 'out' | 'in' ; @@ -2854,10 +2834,21 @@ finalizer_body // Source: §15.16.1 General record_class_declaration : attributes? class_modifier* 'partial'? 'record' 'class'? identifier - type_parameter_list? delimited_parameter_list? class_base? + type_parameter_list? delimited_parameter_list? class_base? type_parameter_constraints_clause* record_class_body ; +// Source: §15.16.2 Class base specification +base_argument_list + : '(' argument_list? ')' + ; + +// Source: §15.16.3 Record class body +record_class_body + : class_body + | ';' + ; + // Source: §16.2.1 General struct_declaration : non_record_struct_declaration @@ -2865,20 +2856,9 @@ struct_declaration ; non_record_struct_declaration - : non_record_struct_without_positional_members - | non_record_struct_with_positional_members - ; - -non_record_struct_without_positional_members : attributes? struct_modifier* 'ref'? 'partial'? 'struct' identifier type_parameter_list? struct_interfaces? - type_parameter_constraints_clause* struct_body - ; - -non_record_struct_with_positional_members - : attributes? struct_modifier* 'ref'? 'partial'? 'struct' - identifier type_parameter_list? delimited_parameter_list struct_interfaces? - type_parameter_constraints_clause* struct_body + type_parameter_constraints_clause* struct_body ';'? ; record_struct_declaration @@ -2911,8 +2891,7 @@ struct_interfaces // Source: §16.2.6 Struct body struct_body - : '{' struct_member_declaration* '}' ';'? - | ';' + : '{' struct_member_declaration* '}' ; // Source: §16.3.1 General @@ -2930,14 +2909,20 @@ struct_member_declaration | fixed_size_buffer_declaration // unsafe code support ; -// Source: §16.5.1 General +// Source: §16.4.1 General record_struct_declaration : attributes? struct_modifier* 'partial'? 'record' 'struct' identifier type_parameter_list? delimited_parameter_list? struct_interfaces? - type_parameter_constraints_clause* struct_body + type_parameter_constraints_clause* record_struct_body + ; + +// Source: §16.4.3 Record struct body +record_struct_body + : struct_body ';'? + | ';' ; -// Source: §16.8.8.2 Ref fields +// Source: §16.6.8.2 Ref fields struct_field_declaration : attributes? field_modifier* ('readonly'? 'ref' 'readonly'?)? type variable_declarators ';' @@ -2962,7 +2947,7 @@ variable_initializer interface_declaration : attributes? interface_modifier* 'partial'? 'interface' identifier variant_type_parameter_list? interface_base? - type_parameter_constraints_clause* interface_body + type_parameter_constraints_clause* interface_body ';'? ; // Source: §19.2.2 Interface modifiers @@ -2997,8 +2982,7 @@ interface_base // Source: §19.3 Interface body interface_body - : '{' interface_member_declaration* '}' ';'? - | ';' + : '{' interface_member_declaration* '}' ; // Source: §19.4.1 General @@ -3016,7 +3000,7 @@ interface_member_declaration // Source: §20.2 Enum declarations enum_declaration - : attributes? enum_modifier* 'enum' identifier enum_base? enum_body + : attributes? enum_modifier* 'enum' identifier enum_base? enum_body ';'? ; enum_base @@ -3029,9 +3013,8 @@ integral_type_name ; enum_body - : '{' enum_member_declarations? '}' ';'? - | '{' enum_member_declarations ',' '}' ';'? - | ';' + : '{' enum_member_declarations? '}' + | '{' enum_member_declarations ',' '}' ; // Source: §20.3 Enum modifiers @@ -3179,7 +3162,7 @@ dataptr_type // Source: §24.3.3 Function pointers funcptr_type - : 'delegate' '*' calling_convention_specifier? + : 'delegate' '*' calling_convention_specifier? '<' funcptr_parameter_list funcptr_return_type '>' ; diff --git a/standard/interfaces.md b/standard/interfaces.md index db1bf8475..5a46311c5 100644 --- a/standard/interfaces.md +++ b/standard/interfaces.md @@ -575,11 +575,11 @@ For a type `T` that is a struct or a class that implements interfaces `I2` and ` ### 19.4.11 Interface member access -Interface members are accessed through member access ([§12.8.7](expressions.md#1287-member-access)) and indexer access ([§12.8.12.5](expressions.md#128125-indexer-access)) expressions of the form `I.M` and `I[A]`, where `I` is an interface type, `M` is a constant, field, method, property, or event of that interface type, and `A` is an indexer argument list. +Interface members are accessed through member access ([§12.8.7](expressions.md#1287-member-access)) and indexer access ([§12.8.12.4](expressions.md#128124-indexer-access)) expressions of the form `I.M` and `I[A]`, where `I` is an interface type, `M` is a constant, field, method, property, or event of that interface type, and `A` is an indexer argument list. In a class `D`, with direct or indirect base class `B`, where `B` directly or indirectly implements interface `I` and `I` defines a method `M()`, the expression `base.M()` is valid only if `base.M()` staticly ([§12.3](expressions.md#123-static-and-dynamic-binding)) binds to an implementation of `M()` in a class type. -For interfaces that are strictly single-inheritance (each interface in the inheritance chain has exactly zero or one direct base interface), the effects of the member lookup ([§12.5](expressions.md#125-member-lookup)), method invocation ([§12.8.10.2](expressions.md#128102-method-invocations)), and indexer access ([§12.8.12.5](expressions.md#128125-indexer-access)) rules are exactly the same as for classes and structs: More derived members hide less derived members with the same name or signature. However, for multiple-inheritance interfaces, ambiguities can occur when two or more unrelated base interfaces declare members with the same name or signature. This subclause shows several examples, some of which lead to ambiguities and others which do not. In all cases, explicit casts can be used to resolve the ambiguities. +For interfaces that are strictly single-inheritance (each interface in the inheritance chain has exactly zero or one direct base interface), the effects of the member lookup ([§12.5](expressions.md#125-member-lookup)), method invocation ([§12.8.10.2](expressions.md#128102-method-invocations)), and indexer access ([§12.8.12.4](expressions.md#128124-indexer-access)) rules are exactly the same as for classes and structs: More derived members hide less derived members with the same name or signature. However, for multiple-inheritance interfaces, ambiguities can occur when two or more unrelated base interfaces declare members with the same name or signature. This subclause shows several examples, some of which lead to ambiguities and others which do not. In all cases, explicit casts can be used to resolve the ambiguities. > *Example*: In the following code > @@ -933,7 +933,7 @@ A *type_parameter_constraints_clause* on an explicit interface member implementa > > *end note* -For an explicit interface member implementation to be valid, the class, struct, or interface shall name an interface in its base class or base interface list that contains a member whose qualified interface member name, type, number of type parameters, and parameter types exactly match those of the explicit interface member implementation. If an interface function member has a parameter array, the corresponding parameter of an associated explicit interface member implementation is allowed, but not required, to have the `params` modifier. If the interface function member does not have a parameter array then an associated explicit interface member implementation shall not have a parameter array. +For an explicit interface member implementation to be valid, the class, struct, or interface shall name an interface in its base class or base interface list that contains a member whose qualified interface member name, type, number of type parameters, and parameter types exactly match those of the explicit interface member implementation. If an interface function member has a parameter collection, the corresponding parameter of an associated explicit interface member implementation is allowed, but not required, to have the `params` modifier. If the interface function member does not have a parameter collection then an associated explicit interface member implementation shall not have a parameter collection. For an explicit interface member implementation of a method, property, or indexer that has a return type, there shall be an identity conversion or (if the member has a value return) an implicit reference conversion from the return type of the explicit interface member implementation to the return type of every override of the interface member that is declared in a (direct or indirect) base interface. diff --git a/standard/ranges.md b/standard/ranges.md index a243b62a7..ed01e8a66 100644 --- a/standard/ranges.md +++ b/standard/ranges.md @@ -16,7 +16,7 @@ Under the model a type is classified as: > *Note*: The model does not require that a slice of the type can be set, but a type may support it as an extension of the model. *end note* -The model is supported for single-dimensional arrays ([§12.8.12.2](expressions.md#128122-array-access)) and strings ([§12.8.12.4](expressions.md#128124-string-access)). +The model is supported for single-dimensional arrays ([§12.8.12.2](expressions.md#128122-array-access)) and strings ([§12.8.12.3](expressions.md#128123-string-access)). The model can be supported by any class, struct or interface type which provides appropriate indexers ([§15.9](classes.md#159-indexers)) which implement the model semantics. @@ -143,8 +143,8 @@ This method does **not** check that the return value is in the valid range of `0 `Index` values may be directly used in the *argument_list* of an *element_access* expression ([§12.8.12](expressions.md#12812-element-access)) which is: - an array access and the target is a single-dimensional array ([§12.8.12.2](expressions.md#128122-array-access)); -- a string access ([§12.8.12.4](expressions.md#128124-string-access)) -- an indexer access and the target type has an indexer with corresponding parameters of either `Index` type ([§12.8.12.5](expressions.md#128125-indexer-access)) or of a type to which `Index` values are implicitly convertible; or +- a string access ([§12.8.12.3](expressions.md#128123-string-access)) +- an indexer access and the target type has an indexer with corresponding parameters of either `Index` type ([§12.8.12.4](expressions.md#128124-indexer-access)) or of a type to which `Index` values are implicitly convertible; or - an indexer access and the target type conforms to a sequence pattern for which implicit `Index` support is specified ([§18.4.2](ranges.md#1842-implicit-index-support)). ## 18.3 The Range type @@ -259,9 +259,9 @@ A concrete range value is *empty* if `N` is zero. An empty concrete range may ha `Range` values can be directly used in the *argument_list* of an *element_access* expression ([§12.8.12](expressions.md#12812-element-access)) which is: - an array access and the target is a single-dimensional array ([§12.8.12.2](expressions.md#128122-array-access)); -- a string access ([§12.8.12.4](expressions.md#128124-string-access)); -- an indexer access and the target type has an indexer with corresponding parameters of either `Range` type ([§12.8.12.5](expressions.md#128125-indexer-access)) or of a type to which `Range` values are implicitly convertible; or -- an indexer access ([§12.8.12.5](expressions.md#128125-indexer-access)) and the target type conforms to a sequence pattern for which implicit `Range` support is specified ([§18.4.3](ranges.md#1843-implicit-range-support)). +- a string access ([§12.8.12.3](expressions.md#128123-string-access)); +- an indexer access and the target type has an indexer with corresponding parameters of either `Range` type ([§12.8.12.4](expressions.md#128124-indexer-access)) or of a type to which `Range` values are implicitly convertible; or +- an indexer access ([§12.8.12.4](expressions.md#128124-indexer-access)) and the target type conforms to a sequence pattern for which implicit `Range` support is specified ([§18.4.3](ranges.md#1843-implicit-range-support)). ## 18.4 Pattern-based implicit support for Index and Range @@ -270,8 +270,8 @@ A concrete range value is *empty* if `N` is zero. An empty concrete range may ha If an *element_access* expression ([§12.8.12](expressions.md#12812-element-access)) of the form `E[A]`; where `E` has type `T` and `A` is a single expression implicitly convertible to `Index` or `Range`; fails to be identified as: - an array access ([§12.8.12.2](expressions.md#128122-array-access)), -- a string access ([§12.8.12.4](expressions.md#128124-string-access)), or -- an indexer access ([§12.8.12.5](expressions.md#128125-indexer-access)) as `T` provides no suitable accessible indexer +- a string access ([§12.8.12.3](expressions.md#128123-string-access)), or +- an indexer access ([§12.8.12.4](expressions.md#128124-indexer-access)) as `T` provides no suitable accessible indexer then implicit support for the expression is provided if `T` conforms to a particular pattern. If `T` does not conform to this pattern then a compile-time error occurs. diff --git a/standard/structs.md b/standard/structs.md index fe4864a62..6afc30857 100644 --- a/standard/structs.md +++ b/standard/structs.md @@ -49,13 +49,13 @@ record_struct_body ; ``` -There are two kinds of struct: ***non-record struct***, as declared by *non_record_struct_declaration*, and ***record struct***, as declared by *record_struct_declaration*. A non-record struct is the kind of struct that C# has supported since the language’s inception. Record structs were added much later and are discussed in [§16.5](structs.md#165-record-structs). The differences between the two kinds are discussed in [§16.7](structs.md#167-record-struct-and-non-record-struct-differences). +There are two kinds of struct: ***non-record struct***, as declared by *non_record_struct_declaration*, and ***record struct***, as declared by *record_struct_declaration*. A non-record struct is the kind of struct that C# has supported since the language’s inception. Record structs were added much later and are discussed in [§16.4](structs.md#164-record-structs). The differences between the two kinds are discussed in [§16.5](structs.md#165-record-struct-and-non-record-struct-differences). A *non_record_struct_declaration* can have one of two almost identical forms: *non_record_struct_without_positional_members* and *non_record_struct_with_positional_members*. A *non_record_struct_without_positional_members* consists of an optional set of *attributes* ([§23](attributes.md#23-attributes)), followed by an optional set of *struct_modifier*s ([§16.2.2](structs.md#1622-struct-modifiers)), followed by an optional `ref` modifier ([§16.2.3](structs.md#1623-ref-modifier)), followed by an optional partial modifier ([§15.2.7](classes.md#1527-partial-type-declarations)), followed by the keyword `struct` and an *identifier* that names the struct, followed by an optional *type_parameter_list* specification ([§15.2.3](classes.md#1523-type-parameters)), followed by an optional *struct_interfaces* specification ([§16.2.5](structs.md#1625-struct-interfaces)), followed by an optional *type_parameter_constraints-clauses* specification ([§15.2.5](classes.md#1525-type-parameter-constraints)), followed by a *struct_body* ([§16.2.6](structs.md#1626-struct-body)), optionally followed by a semicolon. -A *non_record_struct_with_positional_members* has the same syntax but requires a *delimited_parameter_list*, as shown above in that grammar rule. For a discussion of *delimited_parameter_list*, see [§15.11.6](classes.md#15116-primary-constructors). +A *non_record_struct_with_positional_members* has the same syntax but requires a *delimited_parameter_list*, as shown above in that grammar rule. For a discussion of *delimited_parameter_list*, see §prim-constructor. A struct having a required member ([§15.7.1](classes.md#1571-general)) directly (that is, not through inheritance) shall be treated as if it were decorated with the attribute `System.Runtime.CompilerServices.RequiredMemberAttribute` ([§23.5.12.2](attributes.md#235122-the-requiredmember-attribute)). A *struct_declaration* shall not supply *type_parameter_constraints_clause*s unless it also supplies a *type_parameter_list*. @@ -100,7 +100,7 @@ When an instance of a readonly struct is passed to a method, its `this` is treat ### 16.2.3 Ref modifier -The `ref` modifier indicates that the *non_record_struct_declaration* declares a type whose instances are allocated on the execution stack. These types are called ***ref struct*** types. The `ref` modifier declares that instances may contain ref-like fields, and shall not be copied out of its safe-context ([§16.8.15](structs.md#16815-safe-context-constraint)). The rules for determining the safe context of a ref struct are described in [§16.8.15](structs.md#16815-safe-context-constraint). +The `ref` modifier indicates that the *non_record_struct_declaration* declares a type whose instances are allocated on the execution stack. These types are called ***ref struct*** types. The `ref` modifier declares that instances may contain ref-like fields, and shall not be copied out of its safe-context ([§16.6.15](structs.md#16615-safe-context-constraint)). The rules for determining the safe context of a ref struct are described in [§16.6.15](structs.md#16615-safe-context-constraint). It is a compile-time error if a ref struct type is used in any of the following contexts: @@ -158,7 +158,7 @@ The *struct_body*s `{}`, `{};`, and `;` are equivalent, and the *struct_body*s ` ### 16.3.1 General -The members of a struct consist of the members introduced by its *struct_member_declaration*s, the members inherited from the type `System.ValueType``, and any members implicitly provided by the implementation ([§16.5.3](structs.md#1653-implicit-record-struct-members)). +The members of a struct consist of the members introduced by its *struct_member_declaration*s, the members inherited from the type `System.ValueType``, and any members implicitly provided by the implementation ([§16.4.4](structs.md#1644-implicit-record-struct-members)). ```ANTLR struct_member_declaration @@ -178,11 +178,11 @@ struct_member_declaration *fixed_size_buffer_declaration* ([§24.8.2](unsafe-code.md#2482-fixed-size-buffer-declarations)) is only available in unsafe code ([§24](unsafe-code.md#24-unsafe-code)). -> *Note*: A *struct_member_declaration* includes all *class_member_declaration* alternatives except *finalizer_declaration*, and adds *struct_field_declaration* which supports ref fields ([§16.8.8.2](structs.md#16882-ref-fields)). *end note* +> *Note*: A *struct_member_declaration* includes all *class_member_declaration* alternatives except *finalizer_declaration*, and adds *struct_field_declaration* which supports ref fields ([§16.6.8.2](structs.md#16682-ref-fields)). *end note* -Fields in structs support capabilities not supported in classes. See [§16.8.8.2](structs.md#16882-ref-fields) for details. +Fields in structs support capabilities not supported in classes. See [§16.6.8.2](structs.md#16682-ref-fields) for details. -Except for the differences noted in [§16.8](structs.md#168-class-and-struct-differences), the descriptions of class members provided in [§15.3](classes.md#153-class-members) through [§15.12](classes.md#1512-static-constructors) apply to struct members as well. +Except for the differences noted in [§16.6](structs.md#166-class-and-struct-differences), the descriptions of class members provided in [§15.3](classes.md#153-class-members) through [§15.12](classes.md#1512-static-constructors) apply to struct members as well. ### 16.3.2 Readonly members @@ -224,17 +224,17 @@ An instance member definition or accessor of an instance property, indexer, or e > > The `readonly` method `AddMessage` can change the state of a message list. The `InitializeMessages` member can clear and re-initialize the list of messages. In the case of `AddMessage`, the `readonly` modifier is valid. In the case of `InitializeMessages`, adding the `readonly` modifier is invalid. *end example* -## 16.4 Primary constructors +## §struct-prim-constructors Primary constructors -As with a non-record class, a non-record struct with a *delimited_parameter_list* has a primary constructor ([§15.11.6](classes.md#15116-primary-constructors)) provided by the implementation. The semantics of the non-record class version apply here as well and are augmented by the text in this subclause. +As with a non-record class, a non-record struct with a *delimited_parameter_list* has a primary constructor (§prim-constructor) provided by the implementation. The semantics of the non-record class version apply here as well and are augmented by the text in this subclause. In the case of a non-record class, the implementation shall provide a private, init-only field for each parameter. However, for a non-record struct, the storage is read-write and provided in some unspecified manner. Instance field declarations for a non-record struct are permitted to include variable initializers. If there is no primary constructor, the instance initializers execute as part of the parameterless constructor. Otherwise, at runtime the primary constructor executes the instance initializers appearing in the *struct_body*. -## 16.5 Record structs +## 16.4 Record structs -### 16.5.1 General +### 16.4.1 General A record struct is a specialized value type that is optimized for storing data rather than behavior. It provides built-in functionality that would normally require significant “boilerplate” code in a non-record struct, such as value-based equality and easy immutability. @@ -254,29 +254,29 @@ At most only one *record_struct_declaration* containing `partial` may provide a The parameters in *delimited_parameter_list* shall not have `ref`, `out` or `this` modifiers; however, `in` and `params` modifiers are permitted. -### 16.5.2 Struct members +### 16.4.2 Struct members It is an error for a member of a record struct to be named `Clone`. It is an error for an instance field of a record struct to have an unsafe type. -### 16.5.3 Implicit record struct members +### 16.4.4 Implicit record struct members -#### 16.5.3.1 General +#### 16.4.4.1 General In the case of a record struct, members are provided by the implementation unless a member with a “matching” signature is declared in the *struct_body* or an accessible concrete non-virtual member with a “matching” signature is inherited. A matching member prevents the implementation from providing that member only, not any other provided members. Two members are considered matching if they have the same signature or would be considered “hiding” in an inheritance scenario. (See Signatures and overloading [§7.5](basic-concepts.md#75-signatures-and-overloading).) The members provided by the implementation are described in the following subclauses. -#### 16.5.3.2 Primary constructors +#### 16.4.4.2 Primary constructors -The primary constructor of a record struct is like that of a non-record struct ([§16.4](structs.md#164-primary-constructors)), with the following difference: Each parameter value is stored in a corresponding private instance field having a corresponding property with set and get accessors. +The primary constructor of a record struct is like that of a non-record struct (§struct-prim-constructors), with the following difference: Each parameter value is stored in a corresponding private instance field having a corresponding property with set and get accessors. Instance field declarations for a non-record struct are permitted to include variable initializers. If there is no primary constructor, the instance initializers execute as part of the parameterless constructor. Otherwise, at runtime the primary constructor executes the instance initializers appearing in the *struct_body*. -#### 16.5.3.3 Equality members +#### 16.4.4.3 Equality members -The provided equality members are similar to those for a record class ([§15.16.4.3](classes.md#151643-equality-members)), except for the lack of method `EqualityContract`, null checks, or inheritance. +The provided equality members are similar to those for a record class ([§15.16.6.3](classes.md#151663-equality-members)), except for the lack of method `EqualityContract`, null checks, or inheritance. A record struct `R` implements `System.IEquatable` and includes a synthesized strongly-typed overload of `Equals(R other)`, which is public, as follows: @@ -354,7 +354,7 @@ The provided override of `GetHashCode()` shall return an `int` result of combini > > *end example* -#### 16.5.3.4 Printing members +#### 16.4.4.4 Printing members A record struct includes a provided method, declared as follows: @@ -441,23 +441,23 @@ This method performs the following tasks: > > *end example* -#### 16.5.3.5 Positional record struct members +#### 16.4.4.5 Positional record struct members -##### 16.5.3.5.1 General +##### 16.4.4.5.1 General As well as providing the members described in the preceding subclauses, positional record structs ([§16.2.1](structs.md#1621-general)) result in the implementation providing additional members with the same conditions as the other provided members, as described in the following subclauses. -##### 16.5.3.5.2 Primary constructor +##### 16.4.4.5.2 Primary constructor -As with a record class, a record struct with a *delimited_parameter_list* has a primary constructor ([§15.16.4.6.2](classes.md#1516462-primary-constructor)) provided by the implementation. The semantics of the record class version apply here as well and are augmented by the text in this subclause. +As with a record class, a record struct with a *delimited_parameter_list* has a primary constructor ([§15.16.6.6.2](classes.md#1516662-primary-constructor)) provided by the implementation. The semantics of the record class version apply here as well and are augmented by the text in this subclause. In the case of a record class, the implementation shall provide a private, init-only field for each parameter. However, for a record struct, the storage is read-write and provided in some unspecified manner. Instance field declarations for a record struct are permitted to include variable initializers. If there is no primary constructor, the instance initializers execute as part of the parameterless constructor. Otherwise, at runtime the primary constructor executes the instance initializers appearing in the *record_struct_body*. -The definite assignment rules for struct instance constructors ([§16.8.9](structs.md#1689-constructors), [§12.8.14](expressions.md#12814-this-access)) apply to the primary constructor of record structs. As for any other struct instance constructor without a `this()` initializer, any instance field that is not definitely assigned by the primary constructor is implicitly initialized to its default value in the initialization phase that runs before the body of the primary constructor. +The definite assignment rules for struct instance constructors ([§16.6.9](structs.md#1669-constructors), [§12.8.14](expressions.md#12814-this-access)) apply to the primary constructor of record structs. As for any other struct instance constructor without a `this()` initializer, any instance field that is not definitely assigned by the primary constructor is implicitly initialized to its default value in the initialization phase that runs before the body of the primary constructor. -##### 16.5.3.5.3 Properties +##### 16.4.4.5.3 Properties For each parameter of a *delimited_parameter_list* that has the same name and type as an explicitly declared instance field, the remainder of this subclause does not apply. @@ -479,16 +479,16 @@ For a record struct: - Attributes may be applied to the provided auto-property and its backing field by using `property:` or `field:` targets, respectively, for attributes syntactically applied to the corresponding record struct parameter. -##### 16.5.3.5.4 Deconstruct +##### 16.4.4.5.4 Deconstruct A positional record struct with at least one parameter provides a public `void`-returning instance method called `Deconstruct` with an out parameter declaration for each parameter of the primary constructor declaration. Each parameter of `Deconstruct` has the same type as the corresponding parameter of the primary constructor declaration. The body of the method assigns each parameter of the Deconstruct method to the value from an instance member access to a member of the same name. If the instance members accessed in the body do not include a property with a non-`readonly` `get` accessor, then the synthesized `Deconstruct` method is `readonly`. The method can be declared explicitly. It is an error if the explicit declaration does not match the expected signature or accessibility, or is static. -## 16.6 Inline arrays +## §InlineArray Inline arrays -A struct type decorated with the attribute `System.Runtime.CompilerServices.InlineArrayAttribute` ([§23.5.14](attributes.md#23514-the-inlinearray-attribute)) is an ***inline array type***, which is a managed type. An instance of that type is an ***inline array***, a structure that contains a contiguous block of a given number of elements of the same type, and nothing else. It’s the safe-code equivalent of unsafe-code’s fixed-size buffer ([§24.8](unsafe-code.md#248-fixed-size-buffers)). +A struct type decorated with the attribute `System.Runtime.CompilerServices.InlineArrayAttribute` (§InlineArrayAttribute) is an ***inline array type***, which is a managed type. An instance of that type is an ***inline array***, a structure that contains a contiguous block of a given number of elements of the same type, and nothing else. It’s the safe-code equivalent of unsafe-code’s fixed-size buffer ([§24.8](unsafe-code.md#248-fixed-size-buffers)). With some limitations (see later below), an inline array can be used like an array ([§17](arrays.md#17-arrays)). @@ -545,7 +545,7 @@ There are a number of restrictions on the instance field’s declaration: An inline array is a collection; as such, it can be iterated over by a `foreach` statement, as shown. -The elements of the inline array can be accessed for read or write via subscripting ([§12.8.12.3](expressions.md#128123-inline-array-element-access)). +The elements of the inline array can be accessed for read or write via subscripting (§InlineArrayElementAccess). A list pattern ([§11.2.11](patterns.md#11211-list-pattern)) shall not be used in the context of an inline array. @@ -555,7 +555,7 @@ Any indexers or `Slice` methods declared for an inline array type that have sign > *Example*: Consider the following: > > -> ```csharp +```csharp > var buffer = new Buffer(); > int x = buffer[2]; // element access > @@ -575,7 +575,7 @@ Any indexers or `Slice` methods declared for an inline array type that have sign > > Even though the struct declares an indexer taking an `int` argument, that indexer is not used by element access `buffer[2]`. *end example* -## 16.7 Record struct and non-record struct differences +## 16.5 Record struct and non-record struct differences A record struct differs from a non-record struct in several important ways: @@ -586,22 +586,22 @@ A record struct differs from a non-record struct in several important ways: - It shall not have a member called `Clone`. - It shall not have an instance field with an unsafe type. -## 16.8 Class and struct differences +## 16.6 Class and struct differences -### 16.8.1 General +### 16.6.1 General Structs differ from classes in several important ways: -- Structs are value types ([§16.8.2](structs.md#1682-value-semantics)). -- All struct types implicitly inherit from the class `System.ValueType` ([§16.8.3](structs.md#1683-inheritance)). -- Assignment to a variable of a struct type creates a *copy* of the value being assigned ([§16.8.4](structs.md#1684-assignment)). -- The default value of a struct is the value produced by setting all fields to their default value ([§16.8.5](structs.md#1685-default-values)). -- Boxing and unboxing operations are used to convert between a struct type and certain reference types ([§16.8.6](structs.md#1686-boxing-and-unboxing)). -- The meaning of `this` is different within struct members ([§16.8.7](structs.md#1687-meaning-of-this)). +- Structs are value types ([§16.6.2](structs.md#1662-value-semantics)). +- All struct types implicitly inherit from the class `System.ValueType` ([§16.6.3](structs.md#1663-inheritance)). +- Assignment to a variable of a struct type creates a *copy* of the value being assigned ([§16.6.4](structs.md#1664-assignment)). +- The default value of a struct is the value produced by setting all fields to their default value ([§16.6.5](structs.md#1665-default-values)). +- Boxing and unboxing operations are used to convert between a struct type and certain reference types ([§16.6.6](structs.md#1666-boxing-and-unboxing)). +- The meaning of `this` is different within struct members ([§16.6.7](structs.md#1667-meaning-of-this)). - A struct is not permitted to declare a finalizer. - Event declarations, property declarations, property accessors, indexer declarations, and method declarations are permitted to have the modifier `readonly` while that is not generally permitted for those same member kinds in classes. -### 16.8.2 Value semantics +### 16.6.2 Value semantics Structs are value types ([§8.3](types.md#83-value-types)) and are said to have value semantics. Classes, on the other hand, are reference types ([§8.2](types.md#82-reference-types)) and are said to have reference semantics. @@ -668,7 +668,7 @@ With classes, it is possible for two variables to reference the same object, and > > *end example* -### 16.8.3 Inheritance +### 16.6.3 Inheritance All struct types implicitly inherit from the class `System.ValueType`, which, in turn, inherits from class `object`. A struct declaration may specify a list of implemented interfaces, but it is not possible for a struct declaration to specify a base class. @@ -678,7 +678,7 @@ Since inheritance is not supported for structs, the declared accessibility of a Function members in a struct cannot be abstract or virtual, and the `override` modifier is allowed only to override methods inherited from `System.ValueType`. -### 16.8.4 Assignment +### 16.6.4 Assignment Assignment to a variable of a struct type creates a *copy* of the value being assigned. This differs from assignment to a variable of a class type, which copies the reference but not the object identified by the reference. @@ -686,7 +686,7 @@ Similar to an assignment, when a struct is passed as a value parameter or return When a property or indexer of a struct is the target of an assignment, the instance expression associated with the property or indexer access shall be classified as a variable. If the instance expression is classified as a value, a compile-time error occurs. This is described in further detail in [§12.24.2](expressions.md#12242-simple-assignment). -### 16.8.5 Default values +### 16.6.5 Default values As described in [§9.3](variables.md#93-default-values), several kinds of variables are automatically initialized to their default value when they are created. For variables of class types and other reference types, as well as reference variable fields, this default value is `null`. However, since structs are value types that cannot be `null`, the default value of a struct is the value produced by setting all value type fields to their default value and all reference variable fields and reference type fields to `null`. @@ -701,7 +701,7 @@ As described in [§9.3](variables.md#93-default-values), several kinds of variab > > *end example* -The default value of a struct corresponds to the value returned by the default constructor of the struct ([§8.3.3](types.md#833-default-constructors)). When a struct does not declare an explicit parameterless instance constructor, the default constructor is synthesized and always returns the value that results from setting all fields to their default values. The `default` expression always produces the zero-initialized default value, even when a struct declares an explicit parameterless instance constructor ([§16.8.9](structs.md#1689-constructors)). +The default value of a struct corresponds to the value returned by the default constructor of the struct ([§8.3.3](types.md#833-default-constructors)). When a struct does not declare an explicit parameterless instance constructor, the default constructor is synthesized and always returns the value that results from setting all fields to their default values. The `default` expression always produces the zero-initialized default value, even when a struct declares an explicit parameterless instance constructor ([§16.6.9](structs.md#1669-constructors)). > *Note*: Structs should be designed to consider the default initialization state a valid state. In the example > @@ -729,7 +729,7 @@ The default value of a struct corresponds to the value returned by the default c > > *end note* -### 16.8.6 Boxing and unboxing +### 16.6.6 Boxing and unboxing A value of a class type can be converted to type `object` or to an interface type that is implemented by the class simply by treating the reference as another type at compile-time. Likewise, a value of type `object` or a value of an interface type can be converted back to a class type without changing the reference (but, of course, a run-time type check is required in this case). @@ -739,7 +739,7 @@ Since structs are not reference types, these operations are implemented differen For further details on boxing and unboxing, see [§10.2.9](conversions.md#1029-boxing-conversions) and [§10.3.7](conversions.md#1037-unboxing-conversions). -### 16.8.7 Meaning of this +### 16.6.7 Meaning of this The meaning of `this` in a struct differs from the meaning of `this` in a class, as described in [§12.8.14](expressions.md#12814-this-access). When a struct type overrides a virtual method inherited from `System.ValueType` (such as `Equals`, `GetHashCode`, or `ToString`), invocation of the virtual method through an instance of the struct type does not cause boxing to occur. This is true even when the struct is used as a type parameter and the invocation occurs through an instance of the type parameter type. @@ -829,11 +829,11 @@ Similarly, boxing never implicitly occurs when accessing a member on a constrain > > *end example* -### 16.8.8 Fields +### 16.6.8 Fields -#### 16.8.8.1 Field initializers +#### 16.6.8.1 Field initializers -As described in [§16.8.5](structs.md#1685-default-values), the default value of a struct consists of the value that results from setting all value type and reference variable fields to their default value and all reference type fields to `null`. Static and instance fields of a struct are permitted to include variable initializers; however, in the case of an instance field initializer, at least one instance constructor shall also be declared, or for a record struct, a *delimited_parameter_list* shall be present. +As described in [§16.6.5](structs.md#1665-default-values), the default value of a struct consists of the value that results from setting all value type and reference variable fields to their default value and all reference type fields to `null`. Static and instance fields of a struct are permitted to include variable initializers; however, in the case of an instance field initializer, at least one instance constructor shall also be declared, or for a record struct, a *delimited_parameter_list* shall be present. > *Example*: > @@ -867,7 +867,7 @@ When a struct instance constructor has a `this()` constructor initializer that r A *field_declaration* declared directly inside a *struct_declaration* having the *struct_modifier* `readonly` shall have the *field_modifier* `readonly`. -#### 16.8.8.2 Ref fields +#### 16.6.8.2 Ref fields ```ANTLR struct_field_declaration @@ -925,7 +925,7 @@ readonly ref struct RoS `roRefToRwData` is a read-only reference variable, whose referent is seen as a writable `int`. `roRefToRoData` is a read-only reference variable, whose referent is seen as a read-only `int`. The read/write field `rwField` can be written directly, and via the reference variable `roRefToRwData`. -### 16.8.9 Constructors +### 16.6.9 Constructors A struct can declare instance constructors, with zero or more parameters. If a struct has no explicitly declared parameterless instance constructor, one is synthesized, with public accessibility, which always returns the value that results from setting all value type fields to their default value, all reference variable fields to null references, and all reference type fields to `null` ([§8.3.3](types.md#833-default-constructors)). In such a case, any instance field initializers are ignored when that constructor executes. @@ -1027,16 +1027,16 @@ For a struct instance constructor that does not have a `this()` initializer, any > > *end example*] -### 16.8.10 Static constructors +### 16.6.10 Static constructors Static constructors for structs follow most of the same rules as for classes. The execution of a static constructor for a struct type is triggered by the first of the following events to occur within an application domain: - A static member of the struct type is referenced. - An explicitly declared constructor of the struct type is called. -> *Note*: The creation of default values ([§16.8.5](structs.md#1685-default-values)) of struct types does not trigger the static constructor. (An example of this is the initial value of elements in an array.) *end note* +> *Note*: The creation of default values ([§16.6.5](structs.md#1665-default-values)) of struct types does not trigger the static constructor. (An example of this is the initial value of elements in an array.) *end note* -### 16.8.11 Properties +### 16.6.11 Properties A *property_declaration* ([§15.7.1](classes.md#1571-general)) for an instance property in a *struct_declaration* may contain the *property_modifier* `readonly`. However, a static property shall not contain that modifier. @@ -1063,7 +1063,7 @@ Automatically implemented properties ([§15.7.4](classes.md#1574-automatically-i > *Note*: Because the backing field of an auto-property of a struct type is implicitly initialized to its default value in the initialization phase of an instance constructor that does not assign it ([§12.8.14](expressions.md#12814-this-access)), an explicit constructor initializer is not required in order to satisfy the definite-assignment rules for that backing field. *end note* -### 16.8.12 Methods +### 16.6.12 Methods A *method_declaration* ([§15.6.1](classes.md#1561-general)) for an instance method in a *struct_declaration* may contain the *method_modifier* `readonly`. However, a static method shall not contain that modifier. @@ -1075,7 +1075,7 @@ A readonly method may call a sibling property or indexer set accessor that is re All *method_declaration*s of a partial method shall have a `readonly` modifier, or none of them shall have it. -### 16.8.13 Indexers +### 16.6.13 Indexers An *indexer_declaration* ([§15.9](classes.md#159-indexers)) for an instance indexer in a *struct_declaration* may contain the *indexer_modifier* `readonly`. @@ -1087,13 +1087,13 @@ It is a compile-time error for an indexer to have a readonly modifier on all of > *Note*: To correct the error, move the modifier from the accessors to the indexer itself. *end note* -### 16.8.14 Events +### 16.6.14 Events An *event_declaration* ([§15.8.1](classes.md#1581-general)) for an instance, non-field-like event in a *struct_declaration* may contain the *event_modifier* `readonly`. However, a static event shall not contain that modifier. -### 16.8.15 Safe context constraint +### 16.6.15 Safe context constraint -#### 16.8.15.1 General +#### 16.6.15.1 General At compile-time, each expression is associated with a context where that instance and all its fields can be safely accessed, its ***safe-context***. The safe-context is a context, enclosing an expression, which it is safe for the value to escape to. @@ -1113,7 +1113,7 @@ There are four different safe-context values, the same as the ref-safe-context v - For an assignment `e1 = e2` the safe-context of `e2` shall be at least as wide a context as the safe-context of `e1`. - For an assignment to an `out` parameter, the safe-context of the right-hand side shall be at least return-only. -#### 16.8.15.2 Parameter safe context +#### 16.6.15.2 Parameter safe context A parameter of a ref struct type, including the `this` parameter of an instance method, has a safe-context of caller-context. @@ -1121,7 +1121,7 @@ An `out` parameter of a ref struct type has a safe-context of return-only. A `this` parameter in a struct constructor has a safe-context of return-only. -#### 16.8.15.3 Local variable safe context +#### 16.6.15.3 Local variable safe context A local variable of a ref struct type has a safe-context as follows: @@ -1131,19 +1131,19 @@ A local variable of a ref struct type has a safe-context as follows: See [§9.7.2.1](variables.md#9721-general) and [§9.7.2.2](variables.md#9722-local-variable-ref-safe-context). -#### 16.8.15.4 Field safe context +#### 16.6.15.4 Field safe context A reference to a field `e.F`, where the type of `F` is a ref struct type, has a safe-context that is the same as the safe-context of `e`. -#### 16.8.15.5 Operators +#### 16.6.15.5 Operators -The application of a user-defined operator is treated as a method invocation ([§16.8.15.6](structs.md#168156-method-and-property-invocation)). +The application of a user-defined operator is treated as a method invocation ([§16.6.15.6](structs.md#166156-method-and-property-invocation)). For an operator that yields a value, such as `e1 + e2` or `c ? e1 : e2`, the safe-context of the result is the narrowest context among the safe-contexts of the operands of the operator. As a consequence, for a unary operator that yields a value, such as `+e`, the safe-context of the result is the safe-context of the operand. > *Note*: The first operand of a conditional operator is a `bool`, so its safe-context is caller-context. It follows that the resulting safe-context is the narrowest safe-context of the second and third operand. *end note* -#### 16.8.15.6 Method and property invocation +#### 16.6.15.6 Method and property invocation A value resulting from a method invocation `e1.M(e2, ...)` or property invocation `e.P`, where `M()` does not return ref-to-ref-struct, has safe-context of the smallest of the following contexts: @@ -1192,7 +1192,7 @@ A property invocation (either `get` or `set`) is treated as a method invocation > > *end example* -#### 16.8.15.7 Method arguments must match +#### 16.6.15.7 Method arguments must match For any method invocation `e.M(a1, a2, ... aN)`: @@ -1237,7 +1237,7 @@ The presence of `scoped` allows developers to reduce the friction this rule crea > > *end example* -#### 16.8.15.8 Infer safe-context of declaration expressions +#### 16.6.15.8 Infer safe-context of declaration expressions The safe-context of a declaration variable from an `out` argument (`M(x, out var y)`) or deconstruction (`(var x, var y) = M()`) is the narrowest of the following: @@ -1277,7 +1277,7 @@ The safe-context of a declaration variable from an `out` argument (`M(x, out var > > *end example* -#### 16.8.15.9 Object initializer safe context +#### 16.6.15.9 Object initializer safe context The safe-context of an object initializer expression is the narrowest of: @@ -1320,12 +1320,12 @@ The safe-context of an object initializer expression is the narrowest of: > > *end example* -#### 16.8.15.10 stackalloc +#### 16.6.15.10 stackalloc The result of a stackalloc expression has safe-context of function-member. -#### 16.8.15.11 Constructor invocations +#### 16.6.15.11 Constructor invocations A `new` expression that invokes a constructor obeys the same rules as a method invocation that is considered to return the type being constructed. -In addition the safe-context is the smallest of the safe-contexts of all arguments and operands of all object initializer expressions, recursively, if any initializer is present. See [§16.8.15.9](structs.md#168159-object-initializer-safe-context) for details. +In addition the safe-context is the smallest of the safe-contexts of all arguments and operands of all object initializer expressions, recursively, if any initializer is present. See [§16.6.15.9](structs.md#166159-object-initializer-safe-context) for details. diff --git a/standard/types.md b/standard/types.md index 631824230..db2c89099 100644 --- a/standard/types.md +++ b/standard/types.md @@ -272,7 +272,7 @@ Like any other instance constructor, the default constructor of a value type is > > *end example* -A struct type is permitted to declare instance constructors, including a parameterless instance constructor. An explicitly declared parameterless instance constructor shall have public accessibility ([§16.8.9](structs.md#1689-constructors)). +A struct type is permitted to declare instance constructors, including a parameterless instance constructor. An explicitly declared parameterless instance constructor shall have public accessibility ([§16.6.9](structs.md#1669-constructors)). ### 8.3.4 Struct types diff --git a/standard/unsafe-code.md b/standard/unsafe-code.md index c4a7a960a..8effbba7a 100644 --- a/standard/unsafe-code.md +++ b/standard/unsafe-code.md @@ -276,7 +276,7 @@ A ***function pointer*** is a pointer capable of containing the address of a sta ```ANTLR funcptr_type - : 'delegate' '*' calling_convention_specifier? + : 'delegate' '*' calling_convention_specifier? '<' funcptr_parameter_list funcptr_return_type '>' ; @@ -410,7 +410,7 @@ The `&` operator ([§24.6.5](unsafe-code.md#2465-the-address-of-operator)) permi In precise terms, a fixed variable is one of the following: -- A variable resulting from a *simple_name* ([§12.8.4](expressions.md#1284-simple-names)) that refers to a local variable, value parameter, or parameter array, unless the variable is captured by a non-`static` anonymous function ([§12.22.6.2](expressions.md#122262-captured-outer-variables)). +- A variable resulting from a *simple_name* ([§12.8.4](expressions.md#1284-simple-names)) that refers to a local variable, value parameter, or parameter collection, unless the variable is captured by a non-`static` anonymous function ([§12.22.6.2](expressions.md#122262-captured-outer-variables)). - A variable resulting from a *member_access* ([§12.8.7](expressions.md#1287-member-access)) of the form `V.I`, where `V` is a fixed variable of a *struct_type*. - A variable resulting from a *pointer_indirection_expression* ([§24.6.2](unsafe-code.md#2462-pointer-indirection)) of the form `*P`, a *pointer_member_access* ([§24.6.3](unsafe-code.md#2463-pointer-member-access)) of the form `P->I`, or a *pointer_element_access* ([§24.6.4](unsafe-code.md#2464-pointer-element-access)) of the form `P[E]`. @@ -743,7 +743,7 @@ The `&` operator does not require its operand to be definitely assigned, but fol -> *Note*: When a local variable, value parameter, or parameter array is captured by an anonymous function ([§12.8.24](expressions.md#12824-anonymous-method-expressions)), that local variable, parameter, or parameter array is no longer considered to be a fixed variable ([§24.7](unsafe-code.md#247-the-fixed-statement)), but is instead considered to be a moveable variable. Thus it is an error for any unsafe code to take the address of a local variable, value parameter, or parameter array that has been captured by an anonymous function. *end note* +> *Note*: When a local variable, value parameter, or parameter collection is captured by an anonymous function ([§12.8.24](expressions.md#12824-anonymous-method-expressions)), that local variable, parameter, or parameter collection is no longer considered to be a fixed variable ([§24.7](unsafe-code.md#247-the-fixed-statement)), but is instead considered to be a moveable variable. Thus it is an error for any unsafe code to take the address of a local variable, value parameter, or parameter collection that has been captured by an anonymous function. *end note* The case of *unary_expression* designating a method group is described immediately below. @@ -895,7 +895,7 @@ fixed_pointer_initializer Each *fixed_pointer_declarator* declares a local variable of the given *pointer_type* and initializes that local variable with the address computed by the corresponding *fixed_pointer_initializer*. *pointer_type* shall not be *funcptr_type*. A local variable declared in a fixed statement is accessible in any *fixed_pointer_initializer*s occurring to the right of that variable’s declaration, and in the *embedded_statement* of the fixed statement. A local variable declared by a fixed statement is considered read-only. A compile-time error occurs if the embedded statement attempts to modify this local variable (via assignment or the `++` and `--` operators) or pass it as a reference or output parameter. -It is an error to use a captured local variable ([§12.22.6.2](expressions.md#122262-captured-outer-variables)), value parameter, or parameter array in a *fixed_pointer_initializer*. A *fixed_pointer_initializer* can be one of the following: +It is an error to use a captured local variable ([§12.22.6.2](expressions.md#122262-captured-outer-variables)), value parameter, or parameter collection in a *fixed_pointer_initializer*. A *fixed_pointer_initializer* can be one of the following: - The token “`&`” followed by a *variable_reference* ([§9.5](variables.md#95-variable-references)) to a moveable variable ([§24.4](unsafe-code.md#244-fixed-and-moveable-variables)) of a type `T`, provided the type `T*` is implicitly convertible to the pointer type given in the `fixed` statement. In this case, the initializer computes the address of the given variable, and the variable is guaranteed to remain at a fixed address for the duration of the fixed statement. If `T` is a managed type, a warning is produced. - An expression of an *array_type* with elements of a type `T`, provided the type `T*` is implicitly convertible to the pointer type given in the fixed statement. In this case, the initializer computes the address of the first element in the array, and the entire array is guaranteed to remain at a fixed address for the duration of the `fixed` statement. If the array expression is `null` or if the array has zero elements, the initializer computes an address equal to zero. If `T` is a managed type, a warning is produced. @@ -1139,7 +1139,7 @@ fixed_size_buffer_declarator ; ``` -A fixed-size buffer declaration may include a set of attributes ([§23](attributes.md#23-attributes)), a `new` modifier ([§15.3.5](classes.md#1535-the-new-modifier)), accessibility modifiers corresponding to any of the declared accessibilities permitted for struct members ([§16.8.3](structs.md#1683-inheritance)) and an `unsafe` modifier ([§24.2](unsafe-code.md#242-unsafe-contexts)). The attributes and modifiers apply to all of the members declared by the fixed-size buffer declaration. It is an error for the same modifier to appear multiple times in a fixed-size buffer declaration. +A fixed-size buffer declaration may include a set of attributes ([§23](attributes.md#23-attributes)), a `new` modifier ([§15.3.5](classes.md#1535-the-new-modifier)), accessibility modifiers corresponding to any of the declared accessibilities permitted for struct members ([§16.6.3](structs.md#1663-inheritance)) and an `unsafe` modifier ([§24.2](unsafe-code.md#242-unsafe-contexts)). The attributes and modifiers apply to all of the members declared by the fixed-size buffer declaration. It is an error for the same modifier to appear multiple times in a fixed-size buffer declaration. A fixed-size buffer declaration is not permitted to include the `static` modifier. diff --git a/standard/variables.md b/standard/variables.md index 6cece3267..ef6ac2ff9 100644 --- a/standard/variables.md +++ b/standard/variables.md @@ -1237,7 +1237,7 @@ A ***reference return*** is the *variable_reference* returned from a returns-by- All reference variables obey safety rules that ensure the ref-safe-context of the reference variable is not greater than the ref-safe-context of its referent. -> *Note*: The related notion of a *safe-context* is defined in ([§16.8.15](structs.md#16815-safe-context-constraint)), along with associated constraints. *end note* +> *Note*: The related notion of a *safe-context* is defined in ([§16.6.15](structs.md#16615-safe-context-constraint)), along with associated constraints. *end note* For any variable, the ***ref-safe-context*** of that variable is the context where a *variable_reference* ([§9.5](variables.md#95-variable-references)) to that variable is valid. The referent of a reference variable shall have a ref-safe-context that is at least as wide as the ref-safe-context of the reference variable itself. @@ -1429,7 +1429,7 @@ The conditional operator ([§12.21](expressions.md#1221-conditional-operator)), For a variable `c` resulting from a ref-returning function invocation, `ref e1.M(e2, ...)`, where `M()` does not return ref-to-ref-struct, its ref-safe-context is the narrowest of the following contexts: - The caller-context. -- The safe-context ([§16.8.15](structs.md#16815-safe-context-constraint)) contributed by all argument expressions (including the receiver), excluding arguments corresponding to `scoped` parameters and excluding `out` arguments. +- The safe-context ([§16.6.15](structs.md#16615-safe-context-constraint)) contributed by all argument expressions (including the receiver), excluding arguments corresponding to `scoped` parameters and excluding `out` arguments. - The ref-safe-context contributed by all `ref` and `ref readonly` arguments, excluding those corresponding to `scoped ref` parameters and excluding `out` arguments. If `M()` does return ref-to-ref-struct, the ref-safe-context is the narrowest ref-safe-context contributed by all arguments which are ref-to-ref-struct. @@ -1483,7 +1483,7 @@ A `new` expression that invokes a constructor obeys the same rules as a method i ### 9.7.3 The scoped modifier -The contextual keyword `scoped` is used as a modifier to restrict the ref-safe-context ([§9.7.2](variables.md#972-ref-safe-contexts)) or safe-context ([§16.8.15](structs.md#16815-safe-context-constraint)) of a variable. The presence of this modifier requires that related code doesn’t extend the lifetime of the variable. +The contextual keyword `scoped` is used as a modifier to restrict the ref-safe-context ([§9.7.2](variables.md#972-ref-safe-contexts)) or safe-context ([§16.6.15](structs.md#16615-safe-context-constraint)) of a variable. The presence of this modifier requires that related code doesn’t extend the lifetime of the variable. `scoped` shall only be applied to reference variables (which includes non-value parameters) and to variables of a ref struct type. `scoped` shall not be applied to fields, array elements, or return types.