diff --git a/standard/arrays.md b/standard/arrays.md index 024417569..f6a6e1b54 100644 --- a/standard/arrays.md +++ b/standard/arrays.md @@ -2,7 +2,7 @@ ## 17.1 General -An array is a data structure that contains a number of variables that are accessed through computed indices. The variables contained in an array, also called the ***elements*** of the array, are all of the same type, and this type is called the ***element type*** of the array. +An array is a data structure that contains a number of variables that are accessed through computed indices. The variables contained in an array are each called an ***element*** of that array. All elements of that array have the same type, and this type is called the ***element type*** of the array. An array has a rank that determines the number of indices associated with each array element. The rank of an array is also referred to as the dimensions of the array. An array with a rank of one is called a ***single-dimensional array***. An array with a rank greater than one is called a ***multi-dimensional array***. Specific sized multi-dimensional arrays are often referred to as two-dimensional arrays, three-dimensional arrays, and so on. Each dimension of an array has an associated length that is an integral number greater than or equal to zero. The dimension lengths are not part of the type of the array, but rather are established when an instance of the array type is created at run-time. The length of a dimension determines the valid range of indices for that dimension: For a dimension of length `N`, indices can range from `0` to `N – 1` inclusive. The total number of elements in an array is the product of the lengths of each dimension in the array. If one or more of the dimensions of an array have a length of zero, the array is said to be empty. diff --git a/standard/attributes.md b/standard/attributes.md index b3cd07a51..2e9e22c51 100644 --- a/standard/attributes.md +++ b/standard/attributes.md @@ -4,7 +4,7 @@ Much of the C# language enables the programmer to specify declarative information about the entities defined in the program. For example, the accessibility of a method in a class is specified by decorating it with the *method_modifier*s `public`, `protected`, `internal`, and `private`. -C# enables programmers to invent new kinds of declarative information, called ***attributes***. Programmers can then attach attributes to various program entities, and retrieve attribute information in a run-time environment. +C# enables programmers to invent new kinds of declarative information, called ***attribute***s. Programmers can then attach attributes to various program entities, and retrieve attribute information in a run-time environment. > *Note*: For instance, a framework might define a `HelpAttribute` attribute that can be placed on certain program elements (such as classes and methods) to provide a mapping from those program elements to their documentation. *end note* @@ -145,7 +145,7 @@ Attribute classes can have ***positional parameter***s and ***named parameter*** ### 23.2.4 Attribute parameter types -The types of positional and named parameters for an attribute class are limited to the ***attribute parameter types***, which are: +The types of positional and named parameters for an attribute class are limited to the ***attribute parameter type***s, which are: - One of the following types: `bool`, `byte`, `char`, `double`, `float`, `int`, `long`, `sbyte`, `short`, `string`, `uint`, `ulong`, `ushort`. - The type `object`. @@ -156,9 +156,9 @@ The types of positional and named parameters for an attribute class are limited ## 23.3 Attribute specification -***Attribute specification*** is the application of a previously defined attribute to a program entity. An attribute is a piece of additional declarative information that is specified for a program entity. Attributes can be specified at global scope (to specify attributes on the containing assembly or module) and for *type_declaration*s ([§14.7](namespaces.md#147-type-declarations)), *class_member_declaration*s ([§15.3](classes.md#153-class-members)), *interface_member_declaration*s ([§19.4](interfaces.md#194-interface-members)), *struct_member_declaration*s ([§16.3](structs.md#163-struct-members)), *enum_member_declaration*s ([§20.2](enums.md#202-enum-declarations)), *accessor_declaration*s ([§15.7.3](classes.md#1573-accessors)), *event_accessor_declaration*s ([§15.8](classes.md#158-events)), elements of *parameter_list*s ([§15.6.2](classes.md#1562-method-parameters)), and elements of *type_parameter_list*s ([§15.2.3](classes.md#1523-type-parameters)). +Application of a previously defined attribute to a program entity is called ***attribute specification***. An attribute is a piece of additional declarative information that is specified for a program entity. Attributes can be specified at global scope (to specify attributes on the containing assembly or module) and for *type_declaration*s ([§14.7](namespaces.md#147-type-declarations)), *class_member_declaration*s ([§15.3](classes.md#153-class-members)), *interface_member_declaration*s ([§19.4](interfaces.md#194-interface-members)), *struct_member_declaration*s ([§16.3](structs.md#163-struct-members)), *enum_member_declaration*s ([§20.2](enums.md#202-enum-declarations)), *accessor_declaration*s ([§15.7.3](classes.md#1573-accessors)), *event_accessor_declaration*s ([§15.8](classes.md#158-events)), elements of *parameter_list*s ([§15.6.2](classes.md#1562-method-parameters)), and elements of *type_parameter_list*s ([§15.2.3](classes.md#1523-type-parameters)). -Attributes are specified in ***attribute sections***. An attribute section consists of a pair of square brackets, which surround a comma-separated list of one or more attributes. The order in which attributes are specified in such a list, and the order in which sections attached to the same program entity are arranged, is not significant. For instance, the attribute specifications `[A][B]`, `[B][A]`, `[A, B]`, and `[B, A]` are equivalent. +Attributes are specified in ***attribute section***s. An attribute section consists of a pair of square brackets, which surround a comma-separated list of one or more attributes. The order in which attributes are specified in such a list, and the order in which sections attached to the same program entity are arranged, is not significant. For instance, the attribute specifications `[A][B]`, `[B][A]`, `[A, B]`, and `[B, A]` are equivalent. ```ANTLR global_attributes @@ -513,7 +513,7 @@ A class that is decorated with the `AttributeUsage` attribute shall derive from #### 23.5.3.1 General -The attribute `Conditional` enables the definition of ***conditional methods*** and ***conditional attribute classes***. +The attribute `Conditional` enables the definition of ***conditional method***s and ***conditional attribute class***es. #### 23.5.3.2 Conditional methods @@ -958,7 +958,8 @@ Specifies that a given method never returns if the associated `bool` parameter h > { > if (!isNull) > { -> throw new ArgumentException(argumentName, $"argument {argumentName} can't be null"); +> throw new ArgumentException(argumentName, +> $"argument {argumentName} can't be null"); > } > } > @@ -1012,7 +1013,8 @@ Specifies that a nullable value will never be `null` if the method returns (rath > > ```csharp > #nullable enable -> public static void ThrowWhenNull([NotNull] object? value, string valueExpression = "") => +> public static void ThrowWhenNull([NotNull] object? value, +> string valueExpression = "") => > _ = value ?? throw new ArgumentNullException(valueExpression); > > public static void LogMessage(string? message) @@ -1094,7 +1096,8 @@ The iterator won’t have access to the `CancellationToken` argument for `GetAsy > } > } > -> static async IAsyncEnumerable GetStringsAsync([EnumeratorCancellation] CancellationToken token) +> static async IAsyncEnumerable GetStringsAsync( +> [EnumeratorCancellation] CancellationToken token) > { > for (int i = 0; i < 10; i++) > { diff --git a/standard/basic-concepts.md b/standard/basic-concepts.md index 18d32c4e5..d50615ac0 100644 --- a/standard/basic-concepts.md +++ b/standard/basic-concepts.md @@ -39,7 +39,7 @@ The ***effective entry point*** of an application is the entry point declared wi When an application is run, a new ***application domain*** is created. Several different instantiations of an application may exist on the same machine at the same time, and each has its own application domain. An application domain enables application isolation by acting as a container for application state. An application domain acts as a container and boundary for the types defined in the application and the class libraries it uses. Types loaded into one application domain are distinct from the same types loaded into another application domain, and instances of objects are not directly shared between application domains. For instance, each application domain has its own copy of static variables for these types, and a static constructor for a type is run at most once per application domain. Implementations are free to provide implementation-defined policy or mechanisms for the creation and destruction of application domains. -Application startup occurs when the execution environment calls the application’s effective entry point. If the effective entry point declares a parameter, then during application startup, the implementation shall ensure that the initial value of that parameter is a non-null reference to a string array. This array shall consist of non-null references to strings, called ***application parameters***, which are given implementation-defined values by the host environment prior to application startup. The intent is to supply to the application information determined prior to application startup from elsewhere in the hosted environment. +Application startup occurs when the execution environment calls the application’s effective entry point. If the effective entry point declares a parameter, then during application startup, the implementation shall ensure that the initial value of that parameter is a non-null reference to a string array. This array shall consist of non-null references to strings, called ***application parameter***s, which are given implementation-defined values by the host environment prior to application startup. The intent is to supply to the application information determined prior to application startup from elsewhere in the hosted environment. > *Note*: On systems supporting a command line, application parameters correspond to what are generally known as command-line arguments. *end note* @@ -49,7 +49,7 @@ Other than the situations listed above, entry point methods behave like those th ## 7.2 Application termination -***Application termination*** returns control to the execution environment. +The return of control to the execution environment is known as ***application termination***. If the return type of the application’s effective entry point method is `int` and execution completes without resulting in an exception, the value of the `int` returned serves as the application’s ***termination status code***. The purpose of this code is to allow communication of success or failure to the execution environment. If the return type of the effective entry point method is `void` and execution completes without resulting in an exception, the termination status code is `0`. @@ -205,7 +205,7 @@ The textual order in which names are declared is generally of no significance. I ### 7.4.1 General -Namespaces and types have ***members***. +Namespaces and types have ***member***s. > *Note*: The members of an entity are generally available through the use of a qualified name that starts with a reference to the entity, followed by a “`.`” token, followed by the name of the member. *end note* @@ -546,7 +546,7 @@ The following accessibility constraints exist: ## 7.6 Signatures and overloading -Methods, instance constructors, indexers, and operators are characterized by their ***signatures***: +Methods, instance constructors, indexers, and operators are characterized by their ***signature***s: - The signature of a method consists of the name of the method, the number of type parameters, and the type and parameter-passing mode of each of its parameters, considered in the order left to right. For these purposes, any type parameter of the method that occurs in the type of a parameter is identified not by its name, but by its ordinal position in the type parameter list of the method. The signature of a method specifically does not include the return type, parameter names, type parameter names, type parameter constraints, the `params` or `this` parameter modifiers, nor whether parameters are required or optional. - The signature of an instance constructor consists of the type and parameter-passing mode of each of its parameters, considered in the order left to right. The signature of an instance constructor specifically does not include the `params` modifier that may be specified for the right-most parameter, nor whether parameters are required or optional. @@ -972,7 +972,8 @@ A *namespace_or_type_name* is permitted to reference a static class ([§15.2.2.4 > > interface C : A, B > { -> public void Test() { NestedClass.M(); } // ambiguity between A.NestedClass and B.NestedClass +> public void Test() { NestedClass.M(); } // ambiguity between +> // A.NestedClass and B.NestedClass > } > ``` > diff --git a/standard/classes.md b/standard/classes.md index c2cb4d170..5f6820363 100644 --- a/standard/classes.md +++ b/standard/classes.md @@ -488,7 +488,7 @@ The nullable type annotation, `?`, can only be used on a type parameter that has > > *end example* -The ***not null*** constraint specifies that a type argument used for the type parameter should be a non-nullable value type or a non-nullable reference type. A type argument that isn’t a non-nullable value type or a non-nullable reference type is allowed, but a compiler may produce a diagnostic warning. +The not null constraint specifies that a type argument used for the type parameter should be a non-nullable value type or a non-nullable reference type. A type argument that isn’t a non-nullable value type or a non-nullable reference type is allowed, but a compiler may produce a diagnostic warning. Because `notnull` is not a keyword, in *primary_constraint* the not null constraint is always syntactically ambiguous with *class_type*. For compatibility reasons, if a name lookup ([§12.8.4](expressions.md#1284-simple-names)) of the name `notnull` succeeds it shall be treated as a `class_type`. Otherwise it shall be treated as the not null constraint. @@ -515,7 +515,8 @@ Because `notnull` is not a keyword, in *primary_constraint* the not null constra > A x4; > // nonnullable base class requirement allows nonnullable class type argument > B1 x5; -> // possible warning: nonnullable base class requirement prohibits nullable class type argument +> // possible warning: nonnullable base class requirement prohibits nullable +> // class type argument > B1 x6; > // nullable base class requirement allows nonnullable class type argument > B2 x7; @@ -1040,11 +1041,11 @@ A *class_member_declaration* can have any one of the permitted kinds of declared ### 15.3.7 Constituent types -Types that are used in the declaration of a member are called the ***constituent types*** of that member. Possible constituent types are the type of a constant, field, property, event, or indexer, the return type of a method or operator, and the parameter types of a method, indexer, operator, or instance constructor. The constituent types of a member shall be at least as accessible as that member itself ([§7.5.5](basic-concepts.md#755-accessibility-constraints)). +Types that are used in the declaration of a member are called the ***constituent type***s of that member. Possible constituent types are the type of a constant, field, property, event, or indexer, the return type of a method or operator, and the parameter types of a method, indexer, operator, or instance constructor. The constituent types of a member shall be at least as accessible as that member itself ([§7.5.5](basic-concepts.md#755-accessibility-constraints)). ### 15.3.8 Static and instance members -Members of a class are either ***static members*** or ***instance members***. +Members of a class are either ***static member***s or ***instance member***s. > *Note*: Generally speaking, it is useful to think of static members as belonging to classes and instance members as belonging to objects (instances of classes). *end note* @@ -1695,7 +1696,7 @@ A field declaration that declares multiple fields is equivalent to multiple decl ### 15.5.2 Static and instance fields -When a field declaration includes a `static` modifier, the fields introduced by the declaration are ***static fields***. When no `static` modifier is present, the fields introduced by the declaration are ***instance fields***. Static fields and instance fields are two of the several kinds of variables ([§9](variables.md#9-variables)) supported by C#, and at times they are referred to as ***static variables*** and ***instance variables***, respectively. +When a field declaration includes a `static` modifier, the fields introduced by the declaration are ***static field***s. When no `static` modifier is present, the fields introduced by the declaration are ***instance field***s. Static fields and instance fields are two of the several kinds of variables ([§9](variables.md#9-variables)) supported by C#, and at times they are referred to as ***static variable***s and ***instance variable***s, respectively. As explained in [§15.3.8](classes.md#1538-static-and-instance-members), each instance of a class contains a complete set of the instance fields of the class, while there is only one set of static fields for each non-generic class or closed constructed type, regardless of the number of instances of the class or closed constructed type. @@ -1703,7 +1704,7 @@ As explained in [§15.3.8](classes.md#1538-static-and-instance-members), each in #### 15.5.3.1 General -When a *field_declaration* includes a `readonly` modifier, the fields introduced by the declaration are ***readonly fields***. Direct assignments to readonly fields can only occur as part of that declaration or in an instance constructor or static constructor in the same class. (A readonly field can be assigned to multiple times in these contexts.) Specifically, direct assignments to a readonly field are permitted only in the following contexts: +When a *field_declaration* includes a `readonly` modifier, the fields introduced by the declaration are ***readonly field***s. Direct assignments to readonly fields can only occur as part of that declaration or in an instance constructor or static constructor in the same class. (A readonly field can be assigned to multiple times in these contexts.) Specifically, direct assignments to a readonly field are permitted only in the following contexts: - In the *variable_declarator* that introduces the field (by including a *variable_initializer* in the declaration). - For an instance field, in the instance constructors of the class that contains the field declaration, excluding local functions and anonymous functions, and only on the instance being constructed. For a static field, in the static constructor or a static field or property initializer in the class that contains the field declaration, excluding local functions and anonymous functions. These are also the only contexts in which it is valid to pass a readonly field as an output or reference parameter. @@ -1780,7 +1781,7 @@ Constants and readonly fields have different binary versioning semantics. When a ### 15.5.4 Volatile fields -When a *field_declaration* includes a `volatile` modifier, the fields introduced by that declaration are ***volatile fields***. For non-volatile fields, optimization techniques that reorder instructions can lead to unexpected and unpredictable results in multi-threaded programs that access fields without synchronization such as that provided by the *lock_statement* ([§13.13](statements.md#1313-the-lock-statement)). These optimizations can be performed by the compiler, by the run-time system, or by hardware. For volatile fields, such reordering optimizations are restricted: +When a *field_declaration* includes a `volatile` modifier, the fields introduced by that declaration are ***volatile field***s. For non-volatile fields, optimization techniques that reorder instructions can lead to unexpected and unpredictable results in multi-threaded programs that access fields without synchronization such as that provided by the *lock_statement* ([§13.13](statements.md#1313-the-lock-statement)). These optimizations can be performed by the compiler, by the run-time system, or by hardware. For volatile fields, such reordering optimizations are restricted: - A read of a volatile field is called a ***volatile read***. A volatile read has “acquire semantics”; that is, it is guaranteed to occur prior to any references to memory that occur after it in the instruction sequence. - A write of a volatile field is called a ***volatile write***. A volatile write has “release semantics”; that is, it is guaranteed to happen after any memory references prior to the write instruction in the instruction sequence. @@ -3291,7 +3292,7 @@ For returns-by-value and returns-by-ref methods the endpoint of the method body ### 15.7.1 General -A ***property*** is a member that provides access to a characteristic of an object or a class. Examples of properties include the length of a string, the size of a font, the caption of a window, and the name of a customer. Properties are a natural extension of fields—both are named members with associated types, and the syntax for accessing fields and properties is the same. However, unlike fields, properties do not denote storage locations. Instead, properties have ***accessors*** that specify the statements to be executed when their values are read or written. Properties thus provide a mechanism for associating actions with the reading and writing of an object or class’s characteristics; furthermore, they permit such characteristics to be computed. +A ***property*** is a member that provides access to a characteristic of an object or a class. Examples of properties include the length of a string, the size of a font, the caption of a window, and the name of a customer. Properties are a natural extension of fields—both are named members with associated types, and the syntax for accessing fields and properties is the same. However, unlike fields, properties do not denote storage locations. Instead, properties have ***accessor***s that specify the statements to be executed when their values are read or written. Properties thus provide a mechanism for associating actions with the reading and writing of an object or class’s characteristics; furthermore, they permit such characteristics to be computed. Properties are declared using *property_declaration*s: @@ -4035,7 +4036,7 @@ When a property is declared as an override, any overridden accessors shall be ac ### 15.8.1 General -An ***event*** is a member that enables an object or class to provide notifications. Clients can attach executable code for events by supplying ***event handlers***. +An ***event*** is a member that enables an object or class to provide notifications. Clients can attach executable code for events by supplying ***event handler***s. Events are declared using *event_declaration*s: @@ -5513,7 +5514,7 @@ An asynchronous iterator shall support cancellation of the asynchronous operatio ### 15.15.2 Enumerator interfaces -The ***enumerator interfaces*** are the non-generic interface `System.Collections.IEnumerator` and the generic interface `System.Collections.Generic.IEnumerator`. +The ***enumerator interface***s are the non-generic interface `System.Collections.IEnumerator` and the generic interface `System.Collections.Generic.IEnumerator`. The ***asynchronous enumerator interface*** is the generic interface `System.Collections.Generic.IAsyncEnumerator`. @@ -5521,7 +5522,7 @@ For the sake of brevity, in this subclause and its siblings these interfaces are ### 15.15.3 Enumerable interfaces -The ***enumerable interfaces*** are the non-generic interface `System.Collections.IEnumerable` and the generic interfaces `System.Collections.Generic.IEnumerable`. +The ***enumerable interface***s are the non-generic interface `System.Collections.IEnumerable` and the generic interfaces `System.Collections.Generic.IEnumerable`. The ***asynchronous enumerable interface*** is the generic interface `System.Collections.Generic.IAsyncEnumerable`. diff --git a/standard/conversions.md b/standard/conversions.md index 0c047927c..b16d7f407 100644 --- a/standard/conversions.md +++ b/standard/conversions.md @@ -726,7 +726,7 @@ A user-defined explicit conversion from a type `S` to a type `T` exists if a u ### 10.6.1 Nullable Conversions -***Nullable conversions*** permit predefined conversions that operate on non-nullable value types to also be used with nullable forms of those types. For each of the predefined implicit or explicit conversions that convert from a non-nullable value type `S` to a non-nullable value type `T` ([§10.2.2](conversions.md#1022-identity-conversion), [§10.2.3](conversions.md#1023-implicit-numeric-conversions), [§10.2.4](conversions.md#1024-implicit-enumeration-conversions), [§10.2.11](conversions.md#10211-implicit-constant-expression-conversions), [§10.3.2](conversions.md#1032-explicit-numeric-conversions) and [§10.3.3](conversions.md#1033-explicit-enumeration-conversions)), the following nullable conversions exist: +A ***nullable conversion*** permits a predefined conversion that operates on a non-nullable value type to also be used with the nullable form of that type. For each of the predefined implicit or explicit conversions that convert from a non-nullable value type `S` to a non-nullable value type `T` ([§10.2.2](conversions.md#1022-identity-conversion), [§10.2.3](conversions.md#1023-implicit-numeric-conversions), [§10.2.4](conversions.md#1024-implicit-enumeration-conversions), [§10.2.11](conversions.md#10211-implicit-constant-expression-conversions), [§10.3.2](conversions.md#1032-explicit-numeric-conversions) and [§10.3.3](conversions.md#1033-explicit-enumeration-conversions)), the following nullable conversions exist: - An implicit or explicit conversion from `S?` to `T?` - An implicit or explicit conversion from `S` to `T?` diff --git a/standard/expressions.md b/standard/expressions.md index 710c5cea7..083e9fc7a 100644 --- a/standard/expressions.md +++ b/standard/expressions.md @@ -183,7 +183,7 @@ Precedence and associativity can be controlled using parentheses. All unary and binary operators have predefined implementations. In addition, user-defined implementations can be introduced by including operator declarations ([§15.10](classes.md#1510-operators)) in classes and structs. User-defined operator implementations always take precedence over predefined operator implementations: Only when no applicable user-defined operator implementations exist will the predefined operator implementations be considered, as described in [§12.4.4](expressions.md#1244-unary-operator-overload-resolution) and [§12.4.5](expressions.md#1245-binary-operator-overload-resolution). -The ***overloadable unary operators*** are: +The ***overloadable unary operator***s are: > `+ - !` (logical negation only) `~ ++ -- true false` @@ -191,7 +191,7 @@ Only the operators listed above can be overloaded. In particular, it is not poss > *Note*: Although `true` and `false` are not used explicitly in expressions (and therefore are not included in the precedence table in [§12.4.2](expressions.md#1242-operator-precedence-and-associativity)), they are considered operators because they are invoked in several expression contexts: Boolean expressions ([§12.25](expressions.md#1225-boolean-expressions)) and expressions involving the conditional ([§12.19](expressions.md#1219-conditional-operator)) and conditional logical operators ([§12.15](expressions.md#1215-conditional-logical-operators)). *end note* -The ***overloadable binary operators*** are: +The ***overloadable binary operator***s are: > `+ - * / % & | ^ << >> == != > < <= >=` @@ -345,7 +345,7 @@ In both of the above cases, a cast expression can be used to explicitly convert ### 12.4.8 Lifted operators -***Lifted operators*** permit predefined and user-defined operators that operate on non-nullable value types to also be used with nullable forms of those types. Lifted operators are constructed from predefined and user-defined operators that meet certain requirements, as described in the following: +A ***lifted operator*** permits predefined and user-defined operators that operate on a non-nullable value type to also be used with the nullable form of that type. Lifted operators are constructed from predefined and user-defined operators that meet certain requirements, as described in the following: - For the unary operators `+`, `++`, `-`, `--`, `!` (logical negation), `^`, and `~`, a lifted form of an operator exists if the operand and result types are both non-nullable value types. The lifted form is constructed by adding a single `?` modifier to the operand and result types. The lifted operator produces a `null` value if the operand is `null`. Otherwise, the lifted operator unwraps the operand, applies the underlying operator, and wraps the result. - For the binary operators `+`, `-`, `*`, `/`, `%`, `&`, `|`, `^`, `..`, `<<`, and `>>`, a lifted form of an operator exists if the operand and result types are all non-nullable value types. The lifted form is constructed by adding a single `?` modifier to each operand and result type. The lifted operator produces a `null` value if one or both operands are `null` (an exception being the `&` and `|` operators of the `bool?` type, as described in [§12.14.5](expressions.md#12145-nullable-boolean--and--operators)). Otherwise, the lifted operator unwraps the operands, applies the underlying operator, and wraps the result. @@ -3117,8 +3117,10 @@ typeof_expression ; unbound_type_name - : identifier generic_dimension_specifier? ('.' identifier generic_dimension_specifier?)* - | unbound_qualified_alias_member ('.' identifier generic_dimension_specifier?)* + : identifier generic_dimension_specifier? + ('.' identifier generic_dimension_specifier?)* + | unbound_qualified_alias_member + ('.' identifier generic_dimension_specifier?)* ; unbound_qualified_alias_member @@ -6486,7 +6488,7 @@ except when `«v»` is the identifier `«x»`, the translation is #### 12.21.3.8 Transparent identifiers -Certain translations inject range variables with ***transparent identifiers*** denoted by `*`. Transparent identifiers exist only as an intermediate step in the query-expression translation process. +Certain translations inject range variables with ***transparent identifier***s denoted by `*`. Transparent identifiers exist only as an intermediate step in the query-expression translation process. When a query translation injects a transparent identifier, further translation steps propagate the transparent identifier into anonymous functions and anonymous object initializers. In those contexts, transparent identifiers have the following behavior: @@ -6654,7 +6656,8 @@ assignment ; assignment_operator - : '=' 'ref'? | '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' | '<<=' | '??=' + : '=' 'ref'? | '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' | + '<<=' | '??=' | right_shift_assignment ; ``` @@ -6665,12 +6668,12 @@ The `=` operator is called the ***simple assignment operator***. It assigns the The operator `= ref` is called the ***ref assignment operator***. It makes the right operand, which shall be a *variable_reference* ([§9.5](variables.md#95-variable-references)), the referent of the reference variable designated by the left operand. The ref assignment operator is described in [§12.22.3](expressions.md#12223-ref-assignment). -The assignment operators other than the `=` and `= ref` operator are called the ***compound assignment operators***. These operators are processed as follows: +The assignment operators other than the `=` and `= ref` operator are called the ***compound assignment operator***s. These operators are processed as follows: - For the `??=` operator, only if the value of the left-operand is `null`, is the right-operand evaluated and the result assigned to the variable, property, or indexer element given by the left operand. - Otherwise, the indicated operation is performed on the two operands, and then the resulting value is assigned to the variable, property, or indexer element given by the left operand. The compound assignment operators are described in [§12.22.4](expressions.md#12224-compound-assignment). -The `+=` and `-=` operators with an event access expression as the left operand are called the ***event assignment operators***. No other assignment operator is valid with an event access as the left operand. The event assignment operators are described in [§12.22.5](expressions.md#12225-event-assignment). +The `+=` and `-=` operators with an event access expression as the left operand are called the ***event assignment operator***s. No other assignment operator is valid with an event access as the left operand. The event assignment operators are described in [§12.22.5](expressions.md#12225-event-assignment). The assignment operators are right-associative, meaning that operations are grouped from right to left. diff --git a/standard/foreword.md b/standard/foreword.md index fa5feecec..edee198a4 100644 --- a/standard/foreword.md +++ b/standard/foreword.md @@ -1,6 +1,6 @@ # Foreword -This specification replaces ECMA-334:2023. Changes from the previous edition include the addition of the following: +This specification replaces ECMA-334:2023. Changes from the previous edition include the addition of the following features: - enhanced interpolated verbatim strings - asynchronous streams @@ -12,8 +12,9 @@ This specification replaces ECMA-334:2023. Changes from the previous edition inc - `notnull` constraint - null coalescing assignment - nullable reference types +- positional, property, and discard patterns - ranges and indexes - readonly instance members - name shadowing in nested functions - static local functions -- ?? Disposable ref structs +- Disposable ref structs diff --git a/standard/interfaces.md b/standard/interfaces.md index 5ed62239f..2fef96404 100644 --- a/standard/interfaces.md +++ b/standard/interfaces.md @@ -128,7 +128,7 @@ A type `T` is variance-convertible to a type `T *Example*: In the following code > @@ -793,7 +793,7 @@ The base interfaces of a generic class declaration shall satisfy the uniqueness ### 19.6.2 Explicit interface member implementations -For purposes of implementing interfaces, a class, struct, or interface may declare ***explicit interface member implementations***. An explicit interface member implementation is a method, property, event, or indexer declaration that references a qualified interface member name. A class or struct that implements a non-public member in a base interface must declare an explicit interface member implementation. An interface that implements a member in a base interface must declare an explicit interface member implementation. +For purposes of implementing interfaces, a class, struct, or interface may declare ***explicit interface member implementation***s. An explicit interface member implementation is a method, property, event, or indexer declaration that references a qualified interface member name. A class or struct that implements a non-public member in a base interface must declare an explicit interface member implementation. An interface that implements a member in a base interface must declare an explicit interface member implementation. A derived interface member that satisfies interface mapping ([§19.6.5](interfaces.md#1965-interface-mapping)) hides the base interface member ([§7.7.2](basic-concepts.md#772-name-hiding)). The compiler shall issue a warning unless the `new` modifier is present. diff --git a/standard/lexical-structure.md b/standard/lexical-structure.md index 7f9ac6ddd..f47d30a4e 100644 --- a/standard/lexical-structure.md +++ b/standard/lexical-structure.md @@ -2,7 +2,7 @@ ## 6.1 Programs -A C# ***program*** consists of one or more source files, known formally as ***compilation units*** ([§14.2](namespaces.md#142-compilation-units)). Although a compilation unit might have a one-to-one correspondence with a file in a file system, such correspondence is not required. +A C# ***program*** consists of one or more source files, each known formally as a ***compilation unit*** ([§14.2](namespaces.md#142-compilation-units)). Although a compilation unit might have a one-to-one correspondence with a file in a file system, such correspondence is not required. Conceptually speaking, a program is compiled using three steps: @@ -343,7 +343,7 @@ Whitespace ### 6.4.1 General -There are several kinds of ***tokens***: identifiers, keywords, literals, operators, and punctuators. White space and comments are not tokens, though they act as separators for tokens. +There are several kinds of ***token***s: identifiers, keywords, literals, operators, and punctuators. White space and comments are not tokens, though they act as separators for tokens. ```ANTLR token @@ -887,7 +887,7 @@ The type of a *Character_Literal* is `char`. #### 6.4.5.6 String literals -C# supports two forms of string literals: ***regular string literals*** and ***verbatim string literals***. A regular string literal consists of zero or more characters enclosed in double quotes, as in `"hello"`, and can include both simple escape sequences (such as `\t` for the tab character), and hexadecimal and Unicode escape sequences. +C# supports two forms of string literals: ***regular string literal***s and ***verbatim string literal***s. A regular string literal consists of zero or more characters enclosed in double quotes, as in `"hello"`, and can include both simple escape sequences (such as `\t` for the tab character), and hexadecimal and Unicode escape sequences. A verbatim string literal consists of an `@` character followed by a double-quote character, zero or more characters, and a closing double-quote character. @@ -1306,7 +1306,7 @@ fragment PP_Endif ; ``` -Conditional compilation directives shall be written in groups consisting of, in order, a `#if` directive, zero or more `#elif` directives, zero or one `#else` directive, and a `#endif` directive. Between the directives are ***conditional sections*** of source code. Each section is controlled by the immediately preceding directive. A conditional section may itself contain nested conditional compilation directives provided these directives form complete groups. +Conditional compilation directives shall be written in groups consisting of, in order, a `#if` directive, zero or more `#elif` directives, zero or one `#else` directive, and a `#endif` directive. Between the directives are ***conditional section***s of source code. Each section is controlled by the immediately preceding directive. A conditional section may itself contain nested conditional compilation directives provided these directives form complete groups. At most one of the contained conditional sections is selected for normal lexical processing: diff --git a/standard/namespaces.md b/standard/namespaces.md index 286bdf53d..51cfad6ec 100644 --- a/standard/namespaces.md +++ b/standard/namespaces.md @@ -159,7 +159,7 @@ An error occurs if a program declares an extern alias for which no external defi ### 14.5.1 General -***Using directives*** facilitate the use of namespaces and types defined in other namespaces. Using directives impact the name resolution process of *namespace_or_type_name*s ([§7.8](basic-concepts.md#78-namespace-and-type-names)) and *simple_name*s ([§12.8.4](expressions.md#1284-simple-names)), but unlike declarations, *using_directive*s do not contribute new members to the underlying declaration spaces of the compilation units or namespaces within which they are used. +A ***using directive*** facilitates the use of namespaces and types defined in other namespaces. Using directives impact the name resolution process of *namespace_or_type_name*s ([§7.8](basic-concepts.md#78-namespace-and-type-names)) and *simple_name*s ([§12.8.4](expressions.md#1284-simple-names)), but unlike declarations, *using_directive*s do not contribute new members to the underlying declaration spaces of the compilation units or namespaces within which they are used. ```ANTLR using_directive diff --git a/standard/ranges.md b/standard/ranges.md index 55fdbf2df..e82ed551f 100644 --- a/standard/ranges.md +++ b/standard/ranges.md @@ -243,8 +243,8 @@ A concrete range value is *empty* if `N` is zero. An empty concrete range may ha > > ```csharp > var (ix0, len0) = firstQuad.GetOffsetAndLength(6); // ix0 = 0, len0 = 4 -> var (ix1, len1) = nextQuad.GetOffsetAndLength(6); // throws ArgumentOutOfRangeException -> // as range crosses sequence end +> var (ix1, len1) = nextQuad.GetOffsetAndLength(6); // throws +> // ArgumentOutOfRangeException as range crosses sequence end > var (ix2, len2) = wholeSeq.GetOffsetAndLength(6); // ix2 = 0, len2 = 6 > var (ix3, len3) = dropFirst.GetOffsetAndLength(6); // ix3 = 1, len3 = 5 > var (ix4, len4) = dropLast.GetOffsetAndLength(6); // ix4 = 0, len4 = 5 diff --git a/standard/types.md b/standard/types.md index 897df51c4..1db30f80b 100644 --- a/standard/types.md +++ b/standard/types.md @@ -2,7 +2,7 @@ ## 8.1 General -The types of the C# language are divided into two main categories: ***reference types*** and ***value types***. Both value types and reference types may be ***generic types***, which take one or more ***type parameters***. Type parameters can designate both value types and reference types. +The types of the C# language are divided into two main categories: ***reference type*** and ***value type***. A value type or a reference type may be a ***generic type***, which takes one or more ***type parameter***s. Type parameters can designate both value types and reference types. ```ANTLR type @@ -15,7 +15,7 @@ type *pointer_type* ([§24.3](unsafe-code.md#243-pointer-types)) is available only in unsafe code ([§24](unsafe-code.md#24-unsafe-code)). -Value types differ from reference types in that variables of the value types directly contain their data, whereas variables of the reference types store ***references*** to their data, the latter being known as ***objects***. With reference types, it is possible for two variables to reference the same object, and thus possible for operations on one variable to affect the object referenced by the other variable. With value types, the variables each have their own copy of the data, and it is not possible for operations on one to affect the other. +Value types differ from reference types in that a variable of a value types directly contains its data, whereas a variable of a reference type stores a ***reference*** to its data, the latter being known as an ***object***. With reference types, it is possible for two variables to reference the same object, and thus possible for operations on one variable to affect the object referenced by the other variable. With value types, the variables each have their own copy of the data, and it is not possible for operations on one to affect the other. > *Note*: When a variable is a reference or output parameter, it does not have its own storage but references the storage of another variable. In this case, the ref or out variable is effectively an alias for another variable and not a distinct variable. *end note* @@ -91,7 +91,7 @@ A reference type value is a reference to an ***instance*** of the type, the latt ### 8.2.2 Class types -A class type defines a data structure that contains ***data members*** (constants and fields), ***function members*** (methods, properties, events, indexers, operators, instance constructors, finalizers, and static constructors), and nested types. Class types support inheritance, a mechanism whereby derived classes can extend and specialize base classes. Instances of class types are created using *object_creation_expression*s ([§12.8.17.2](expressions.md#128172-object-creation-expressions)). +A class type defines a data structure that contains ***data member***s (constants and fields), ***function member***s (methods, properties, events, indexers, operators, instance constructors, finalizers, and static constructors), and nested types. Class types support inheritance, a mechanism whereby derived classes can extend and specialize base classes. Instances of class types are created using *object_creation_expression*s ([§12.8.17.2](expressions.md#128172-object-creation-expressions)). Class types are described in [§15](classes.md#15-classes). @@ -151,7 +151,7 @@ Delegate types are described in [§21](delegates.md#21-delegates). ### 8.3.1 General -A value type is either a struct type or an enumeration type. C# provides a set of predefined struct types called the ***simple types***. The simple types are identified through keywords. +A value type is either a struct type or an enumeration type. C# provides a set of predefined struct types called the ***simple type***s. The simple types are identified through keywords. ```ANTLR value_type @@ -403,7 +403,7 @@ An enumeration type is a distinct type with named constants. Every enumeration t ### 8.3.11 Tuple types -A tuple type represents an ordered, fixed-length sequence of values with optional names and individual types. The number of elements in a tuple type is referred to as its ***arity***. A tuple type is written `(T1 I1, ..., Tn In)` with n ≥ 2, where the identifiers `I1...In` are optional ***tuple element names***. +A tuple type represents an ordered, fixed-length sequence of values with optional names and individual types. The number of elements in a tuple type is referred to as its ***arity***. A tuple type is written `(T1 I1, ..., Tn In)` with n ≥ 2, where the identifiers `I1...In` are optional ***tuple element name***s. This syntax is shorthand for a type constructed with the types `T1...Tn` from `System.ValueTuple<...>`, which shall be a set of generic struct types capable of directly expressing tuple types of any arity between two and seven inclusive. There does not need to exist a `System.ValueTuple<...>` declaration that directly matches the arity of any tuple type with a corresponding number of type parameters. Instead, tuples with an arity greater than seven are represented with a generic struct type `System.ValueTuple` that in addition to tuple elements has a `Rest` field containing a nested value of the remaining elements, using another `System.ValueTuple<...>` type. Such nesting may be observable in various ways, e.g. via the presence of a `Rest` field. Where only a single additional field is required, the generic struct type `System.ValueTuple` is used; this type is not considered a tuple type in itself. Where more than seven additional fields are required, `System.ValueTuple` is used recursively. @@ -480,7 +480,7 @@ Boxing is described in more detail in [§10.2.9](conversions.md#1029-boxing-conv ### 8.4.1 General -A generic type declaration, by itself, denotes an ***unbound generic type*** that is used as a “blueprint” to form many different types, by way of applying ***type arguments***. The type arguments are written within angle brackets (`<` and `>`) immediately following the name of the generic type. A type that includes at least one type argument is called a ***constructed type***. A constructed type can be used in most places in the language in which a type name can appear. An unbound generic type can only be used within a *typeof_expression* ([§12.8.18](expressions.md#12818-the-typeof-operator)). +A generic type declaration, by itself, denotes an ***unbound generic type*** that is used as a “blueprint” to form many different types, by way of applying ***type argument***s. The type arguments are written within angle brackets (`<` and `>`) immediately following the name of the generic type. A type that includes at least one type argument is called a ***constructed type***. A constructed type can be used in most places in the language in which a type name can appear. An unbound generic type can only be used within a *typeof_expression* ([§12.8.18](expressions.md#12818-the-typeof-operator)). Constructed types can also be used in expressions as simple names ([§12.8.4](expressions.md#1284-simple-names)) or when accessing a member ([§12.8.7](expressions.md#1287-member-access)). @@ -547,7 +547,7 @@ Each type argument shall satisfy any constraints on the corresponding type param ### 8.4.3 Open and closed types -All types can be classified as either ***open types*** or ***closed types***. An open type is a type that involves type parameters. More specifically: +Any type can be classified as either an ***open type*** or a ***closed type***. An open type is a type that involves type parameters. More specifically: - A type parameter defines an open type. - An array type is an open type if and only if its element type is an open type. @@ -633,7 +633,7 @@ As a type, type parameters are purely a compile-time construct. At run-time, eac ## 8.6 Expression tree types -***Expression trees*** permit lambda expressions to be represented as data structures instead of executable code. Expression trees are values of ***expression tree types*** of the form `System.Linq.Expressions.Expression`, where `TDelegate` is any delegate type. For the remainder of this specification these types will be referred to using the shorthand `Expression`. +An ***expression tree*** permits a lambda expression to be represented as a data structure instead of executable code. An expression trees is a value of ***expression tree type*** of the form `System.Linq.Expressions.Expression`, where `TDelegate` is any delegate type. For the remainder of this specification these types will be referred to using the shorthand `Expression`. If a conversion exists from a lambda expression to a delegate type `D`, a conversion also exists to the expression tree type `Expression`. Whereas the conversion of a lambda expression to a delegate type generates a delegate that references executable code for the lambda expression, conversion to an expression tree type creates an expression tree representation of the lambda expression. More details of this conversion are provided in [§10.7.3](conversions.md#1073-evaluation-of-lambda-expression-conversions-to-expression-tree-types). @@ -947,13 +947,17 @@ Later in the method, the code checks that `s` is not a null reference. The null- > { > int length = s.Length; // No warning. s is not null > -> _ = s == null; // Null check by testing equality. The null state of s is maybe null -> length = s.Length; // Warning, and changes the null state of s to not null +> _ = s == null; // Null check by testing equality. The null state of s +> // is maybe null +> length = s.Length; // Warning, and changes the null state of s +> // to not null > -> _ = s?.Length; // The ?. is a null check and changes the null state of s to maybe null +> _ = s?.Length; // The ?. is a null check and changes the null state of s +> // to maybe null > if (s.Length > 4) // Warning. Changes null state of s to not null > { -> _ = s?[4]; // ?[] is a null check and changes the null state of s to maybe null +> _ = s?[4]; // ?[] is a null check and changes the null state of s +> // to maybe null > _ = s.Length; // Warning. s is maybe null > } > } @@ -1013,7 +1017,8 @@ A compiler can treat a property ([§15.7](classes.md#157-properties)) as either > var t = new Test(); > if (t.DisappearingProperty != null) > { -> int len = t.DisappearingProperty.Length; // No warning. A compiler can assume property is stateful +> int len = t.DisappearingProperty.Length; // No warning. A compiler can +> // assume property is stateful > } > } > } @@ -1163,4 +1168,4 @@ A compiler may issue a warning when nullability differs in either direction in t > > *end example* -***End of conditionally normative text*** +**End of conditionally normative text** diff --git a/standard/unsafe-code.md b/standard/unsafe-code.md index 9d6825717..991eab491 100644 --- a/standard/unsafe-code.md +++ b/standard/unsafe-code.md @@ -253,7 +253,7 @@ In an unsafe context, several constructs are available for operating on pointers ## 24.4 Fixed and moveable variables -The address-of operator ([§24.6.5](unsafe-code.md#2465-the-address-of-operator)) and the `fixed` statement ([§24.7](unsafe-code.md#247-the-fixed-statement)) divide variables into two categories: ***Fixed variables*** and ***moveable variables***. +The address-of operator ([§24.6.5](unsafe-code.md#2465-the-address-of-operator)) and the `fixed` statement ([§24.7](unsafe-code.md#247-the-fixed-statement)) divide variables into two categories: ***Fixed variable***s and ***moveable variable***s. Fixed variables reside in storage locations that are unaffected by operation of the garbage collector. (Examples of fixed variables include local variables, value parameters, and variables created by dereferencing pointers.) On the other hand, moveable variables reside in storage locations that are subject to relocation or disposal by the garbage collector. (Examples of moveable variables include fields in objects and elements of arrays.)