diff --git a/standard/README.md b/standard/README.md index d414ddba4..cfa83a50a 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 @@ -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..c01574da6 100644 --- a/standard/arrays.md +++ b/standard/arrays.md @@ -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..83313ea06 100644 --- a/standard/attributes.md +++ b/standard/attributes.md @@ -512,8 +512,9 @@ 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). +- `System.Runtime.CompilerServices.OverloadResolutionPriorityAttribute` (§OvrldResPriAttribute), which specifies the priority of a member during overload resolution. 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 +1580,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 +1590,71 @@ 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. + +### §OvrldResPriAttribute The OverloadResolutionPriority attribute + +The attribute `OverloadResolutionPriority` is used to specify the priority of a member during overload resolution, as an `int` argument to the constructor. The absence of this attribute is equivalent to its presence with an argument of `0`. The higher the number, the higher the priority. All overloads with a lower priority than the highest overload priority are removed from the set of applicable matches. + +A library author might use this attribute to ensure that a new, better overload is preferred over an existing one, to reduce memory allocation, for example. This attribute informs the compiler which overload should be preferred. + +> +> *Example*: Consider the following: +> +> ```csharp +> class Program +> { +> static void Main() +> { +> var c = new C(); +> int[] arr = [1, 2, 3]; +> c.M(arr); // Prints "Span" +> } +> } +> class C +> { +> [OverloadResolutionPriority(1)] +> public void M(params ReadOnlySpan s) => Console.WriteLine("Span"); +> public void M(params int[] a) => Console.WriteLine("Array"); +> } +> ``` +> +> The second method has an implicit priority of zero, and in the absence of the explicit attribute, the second of the overloads would be invoked. However, with the attribute present, the first is invoked instead. +> +> +> Certain uses of this attribute can make a member uncallable, as follows: +> +> ```csharp +> class Program +> { +> static void Main() +> { +> var c = new C(); +> c.M1(1); // Calls C3.M1(long), not M1(int) +> c.M2(1); // Calls C3.M2(int, string), not M2(int) +> c.M3("abc"); // Calls C3.M3(object), not M3(string) +> } +> } +> class C +> { +> public void M1(int i) { } +> [OverloadResolutionPriority(1)] +> public void M1(long l) { } +> +> [Conditional("DEBUG")] +> public void M2(int i) { } +> [OverloadResolutionPriority(1), Conditional("DEBUG")] +> public void M2(int i, [CallerArgumentExpression(nameof(i))] string s = "") { } +> +> public void M3(string s) { } +> [OverloadResolutionPriority(1)] +> public void M3(object o) { } +> } +> ``` +> +> *end example* ## 23.6 Attributes for interoperation diff --git a/standard/basic-concepts.md b/standard/basic-concepts.md index 2fe81f80c..6b7045ba7 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; diff --git a/standard/classes.md b/standard/classes.md index 355c8fcb1..3e5c064ef 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).): @@ -3541,7 +3541,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 +3660,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 +4568,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 +4851,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 +5023,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 +5630,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 +6367,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 +6416,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 +6587,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 +6768,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 +6808,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 +6838,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 +6887,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 +6913,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 +6925,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 +6989,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/expressions.md b/standard/expressions.md index 8799cc6e3..4eb57324c 100644 --- a/standard/expressions.md +++ b/standard/expressions.md @@ -1064,9 +1064,15 @@ Overload resolution is a binding-time mechanism for selecting the best function Each of these contexts defines the set of candidate function members and the list of arguments in its own unique way. For instance, the set of candidates for a method invocation does not include methods marked override ([§12.5](expressions.md#125-member-lookup)), and methods in a base class are not candidates if any method in a derived class is applicable ([§12.8.10.2](expressions.md#128102-method-invocations)). +Each method has an ***overload resolution priority*** of type `int` that is used during the process of resolving a method group. By default, that priority is zero. Its value can be set via `OverloadResolutionPriorityAttribute` (§OvrldResPriAttribute). The overload resolution priority of a member comes from the least-derived declaration of that member. Overload resolution priority is not inherited or inferred from any interface members a type member may implement, and given a member `Mx` that implements an interface member `Mi`, no warning is issued if `Mx` and `Mi` have different overload resolution priorities. + Once the candidate function members and the argument list have been identified, the selection of the best function member is the same in all cases: - First, the set of candidate function members is reduced to those function members that are applicable with respect to the given argument list ([§12.6.4.2](expressions.md#12642-applicable-function-member)). If this reduced set is empty, a compile-time error occurs. +- Then, the reduced set of candidate members is grouped by declaring type. Within each group: + - Candidate function members are ordered by overload resolution priority. If the member is an override, the overload resolution priority comes from the least-derived declaration of that member. + - All members that have a lower overload resolution priority than the highest found within its declaring type group are removed. +- The reduced groups are then recombined into the final set of applicable candidate function members. - Then, the best function member from the set of applicable candidate function members is located. If the set contains only one function member, then that function member is the best function member. Otherwise, the best function member is the one function member that is better than all other function members with respect to the given argument list, provided that each function member is compared to all other function members using the rules in [§12.6.4.3](expressions.md#12643-better-function-member). If there is not exactly one function member that is better than all other function members, then the function member invocation is ambiguous and a binding-time error occurs. The following subclauses define the exact meanings of the terms *applicable function member* and *better function member*. @@ -1300,7 +1306,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 +1341,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)), @@ -1624,7 +1630,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 +1959,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 +2048,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 +2475,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 +2491,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 +2527,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 +2622,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 +2650,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 +2685,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 +2713,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 +3818,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 +3988,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 +4011,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 +4351,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. 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..78a82fe52 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 > 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/standard-library.md b/standard/standard-library.md index 955427a35..9332b0b2b 100644 --- a/standard/standard-library.md +++ b/standard/standard-library.md @@ -977,6 +977,14 @@ namespace System.Runtime.CompilerServices public ModuleInitializerAttribute() { } } + [System.AttributeUsage(System.AttributeTargets.Constructor + | System.AttributeTargets.Method | System.AttributeTargets.Property, + AllowMultiple=false, Inherited=false)] + public sealed class OverloadResolutionPriorityAttribute : Attribute + { + public OverloadResolutionPriorityAttribute(int priority) {} + } + [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Field | System.AttributeTargets.Property | System.AttributeTargets.Struct, AllowMultiple=false, Inherited=false)] @@ -1557,6 +1565,7 @@ The following library types are referenced in this specification. The full names - `global::System.Runtime.CompilerServices.InterpolatedStringHandlerAttribute` - `global::System.Runtime.CompilerServices.ITuple` - `global::System.Runtime.CompilerServices.ModuleInitializerAttribute` +- `global::System.Runtime.CompilerServices.OverloadResolutionPriorityAttribute` - `global::System.Runtime.CompilerServices.RequiredMemberAttribute` - `global::System.Runtime.CompilerServices.TaskAwaiter` - `global::System.Runtime.CompilerServices.TaskAwaiter` 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..6021cb3d4 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 '>' ; @@ -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.