Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions standard/classes.md
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,7 @@
: 'where' type_parameter ':' type_parameter_constraints
;

type_parameter_constraints

Check warning on line 427 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L427

MDC032::Line length 83 > maximum 81
: primary_constraint (',' secondary_constraints)? (',' constructor_constraint)?
| secondary_constraints (',' constructor_constraint)?
| constructor_constraint
Expand Down Expand Up @@ -536,15 +536,15 @@
> static void M()
> {
> // nonnull constraint allows nonnullable struct type argument
> A<int> x1;

Check warning on line 539 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L539

MDC032::Line length 87 > maximum 81
> // possible warning: nonnull constraint prohibits nullable struct type argument
> A<int?> x2;
> // nonnull constraint allows nonnullable class type argument
> A<C> x3;

Check warning on line 543 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L543

MDC032::Line length 86 > maximum 81
> // possible warning: nonnull constraint prohibits nullable class type argument
> A<C?> x4;

Check warning on line 545 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L545

MDC032::Line length 84 > maximum 81
> // nonnullable base class requirement allows nonnullable class type argument
> B1<C> x5;

Check warning on line 547 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L547

MDC032::Line length 82 > maximum 81
> // possible warning: nonnullable base class requirement prohibits nullable
> // class type argument
> B1<C?> x6;
Expand Down Expand Up @@ -2184,9 +2184,9 @@

> *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)). Additionally a *method_declaration* that is contained directly by a *struct_declaration* may include the `readonly` modifier ([§16.5.12](structs.md#16512-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.5.12](structs.md#16512-methods)).

A declaration has a valid combination of modifiers if all of the following are true:
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).):

- The declaration includes a valid combination of access modifiers ([§15.3.6](classes.md#1536-access-modifiers)).
- The declaration does not include the same modifier multiple times.
Expand Down Expand Up @@ -3558,7 +3558,7 @@
> static void Main()
> {
> field = 10;
> Console.WriteLine(Property); // Prints 10

Check warning on line 3561 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L3561

MDC032::Line length 83 > maximum 81
> Property = 20; // This invokes the get accessor, then assigns
> // via the resulting variable reference
> Console.WriteLine(field); // Prints 20
Expand Down Expand Up @@ -4919,7 +4919,7 @@
: '!'
;

overloadable_unary_operator

Check warning on line 4922 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L4922

MDC032::Line length 82 > maximum 81
: '+' | '-' | logical_negation_operator | '~' | '++' | '--' | 'true' | 'false'
;

Expand Down Expand Up @@ -6212,7 +6212,7 @@
> public static bool operator!=(R1? left, R1? right) => !(left == right);
>
> public override int GetHashCode()
> {

Check warning on line 6215 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L6215

MDC032::Line length 93 > maximum 81
> return HashCode.Combine(EqualityComparer<Type>.Default.GetHashCode(EqualityContract),
> EqualityComparer<T1>.Default.GetHashCode(P1));
> }
Expand Down Expand Up @@ -6395,7 +6395,7 @@
> protected virtual bool PrintMembers(StringBuilder builder)
> {
> builder.Append(nameof(P1));
> builder.Append(" = ");

Check warning on line 6398 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L6398

MDC032::Line length 97 > maximum 81
> builder.Append(this.P1); // or builder.Append(this.P1.ToString()); if P1 has a value type
> return true;
> }
Expand Down Expand Up @@ -6426,11 +6426,11 @@
> builder.Append(", ");
> }
> builder.Append(nameof(P2));
> builder.Append(" = ");

Check warning on line 6429 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L6429

MDC032::Line length 86 > maximum 81
> builder.Append(this.P2); // or builder.Append(this.P2); if P2 has a value type
> builder.Append(", ");
> builder.Append(nameof(P3));
> builder.Append(" = ");

Check warning on line 6433 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L6433

MDC032::Line length 86 > maximum 81
> builder.Append(this.P3); // or builder.Append(this.P3); if P3 has a value type
> return true;
> }
Expand Down
21 changes: 16 additions & 5 deletions standard/conversions.md
Original file line number Diff line number Diff line change
Expand Up @@ -741,9 +741,14 @@
- If `E` has a type, let `S` be that type.
- If `S` or `T` are nullable value types, let `Sᵢ` and `Tᵢ` be their underlying types, otherwise let `Sᵢ` and `Tᵢ` be `S` and `T`, respectively.
- If `Sᵢ` or `Tᵢ` are type parameters, let `S₀` and `T₀` be their effective base classes, otherwise let `S₀` and `T₀` be `Sᵢ` and `Tᵢ`, respectively.
- Find the set of types, `D`, from which user-defined conversion operators will be considered. This set consists of `S₀` (if `S₀` exists and is a class or struct), the base classes of `S₀` (if `S₀` exists and is a class), and `T₀` (if `T₀` is a class or struct). A type is added to the set `D` only if an identity conversion to another type already included in the set doesn’t exist.

- Find the set of applicable user-defined and lifted conversion operators, `U`. This set consists of the user-defined and lifted implicit conversion operators declared by the classes or structs in `D` that convert from a type encompassing `E` to a type encompassed by `T`. If `U` is empty, the conversion is undefined and a compile-time error occurs.
- Find the set of applicable user-defined and lifted conversion operators, `U`.
- Find the set of types, `D1`, from which user-defined conversion operators will be considered. This set consists of `S0` (if `S0` is a class or struct), the base classes of `S0` (if `S0` is a class), and `T0` (if `T0` is a class or struct).
- Find the set of applicable user-defined and lifted conversion operators, `U1`. This set consists of the user-defined and lifted implicit conversion operators declared by the classes or structs in `D1` that convert from a type encompassing `S` to a type encompassed by `T`.
- If `U1` is not empty, then `U` is `U1`. Otherwise,
- Find the set of types, `D2`, from which user-defined conversion operators will be considered. This set consists of `Sᵢ` *effective interface set* and their base interfaces (if `Sᵢ` is a type parameter), and `Tᵢ` *effective interface set* (if `Tᵢ` is a type parameter).
- Find the set of applicable user-defined and lifted conversion operators, `U2`. This set consists of the user-defined and lifted implicit conversion operators declared by the interfaces in `D2` that convert from a type encompassing `S` to a type encompassed by `T`.
- If `U2` is not empty, then `U` is `U2`.
- If `U` is empty, the conversion is undefined and a compile-time error occurs.
- Find the most-specific source type, `Sₓ`, of the operators in `U`:
- If `S` exists and any of the operators in `U` convert from `S`, then `Sₓ` is `S`.
- Otherwise, `Sₓ` is the most-encompassed type in the combined set of source types of the operators in `U`. If exactly one most-encompassed type cannot be found, then the conversion is ambiguous and a compile-time error occurs.
Expand All @@ -769,8 +774,14 @@
- If `E` has a type, let `S` be that type.
- If `S` or `T` are nullable value types, let `Sᵢ` and `Tᵢ` be their underlying types, otherwise let `Sᵢ` and `Tᵢ` be `S` and `T`, respectively.
- If `Sᵢ` or `Tᵢ` are type parameters, let `S₀` and `T₀` be their effective base classes, otherwise let `S₀` and `T₀` be `Sᵢ` and `Tᵢ`, respectively.
- Find the set of types, `D`, from which user-defined conversion operators will be considered. This set consists of `S₀` (if `S₀` exists and is a class or struct), the base classes of `S₀` (if `S₀` exists and is a class), `T₀` (if `T₀` is a class or struct), and the base classes of `T₀` (if `T₀` is a class). A type is added to the set `D` only if an identity conversion to another type already included in the set doesn’t exist.
- Find the set of applicable user-defined and lifted conversion operators, `U`. This set consists of the user-defined and lifted implicit or explicit conversion operators declared by the classes or structs in `D` that convert from a type encompassing `E` or encompassed by `S` (if it exists) to a type encompassing or encompassed by `T`. If `U` is empty, the conversion is undefined and a compile-time error occurs.
- Find the set of applicable user-defined and lifted conversion operators, `U`.
- Find the set of types, `D1`, from which user-defined conversion operators will be considered. This set consists of `S0` (if `S0` is a class or struct), the base classes of `S0` (if `S0` is a class), `T0` (if `T0` is a class or struct), and the base classes of `T0` (if `T0` is a class).
- Find the set of applicable user-defined and lifted conversion operators, `U1`. This set consists of the user-defined and lifted implicit or explicit conversion operators declared by the classes or structs in `D1` that convert from a type encompassing or encompassed by `S` to a type encompassing or encompassed by `T`.
- If `U1` is not empty, then `U` is `U1`. Otherwise,
- Find the set of types, `D2`, from which user-defined conversion operators will be considered. This set consists of `Sᵢ` *effective interface set* and their base interfaces (if `Sᵢ` is a type parameter), and `Tᵢ` *effective interface set* and their base interfaces (if `Tᵢ` is a type parameter).
- Find the set of applicable user-defined and lifted conversion operators, `U2`. This set consists of the user-defined and lifted implicit or explicit conversion operators declared by the interfaces in `D2` that convert from a type encompassing or encompassed by `S` to a type encompassing or encompassed by `T`.
- If `U2` is not empty, then `U` is `U2`.
- If `U` is empty, the conversion is undefined and a compile-time error occurs.
- Find the most-specific source type, `Sₓ`, of the operators in `U`:
- If `S` exists and any of the operators in `U` convert from `S`, then `Sₓ` is `S`.
- Otherwise, if any of the operators in `U` convert from types that encompass `E`, then `Sₓ` is the most-encompassed type in the combined set of source types of those operators. If no most-encompassed type can be found, then the conversion is ambiguous and a compile-time error occurs.
Expand Down Expand Up @@ -854,7 +865,7 @@
>
> var amt6 = 66036; // var types amt6 as int
> var dose6 = (Dose)amt6; // amt3 is int, int to ushort conversion added
> // warning as information loss may occur

Check warning on line 868 in standard/conversions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/conversions.md#L868

MDC032::Line length 82 > maximum 81
> Console.WriteLine(dose6); // outputs 500mg, not 66036mg, due to information loss
>
> // Using a constructor instead of user-defined conversion:
Expand Down
41 changes: 25 additions & 16 deletions standard/interfaces.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@

#### 19.2.3.2 Variance safety

The occurrence of variance annotations in the type parameter list of a type restricts the places where types can occur within the type declaration. However, these restrictions do not apply to occurrences of types within a declaration of a static member.
The occurrence of variance annotations in the type parameter list of a type restricts the places where types can occur within the type declaration. However, these restrictions do not apply to occurrences of types within a declaration of a non-virtual, non-abstract static member.

A type `T` is ***output-unsafe*** if one of the following holds:

Expand Down Expand Up @@ -233,15 +233,15 @@
;
```

This clause augments the description of members in classes ([§15.3](classes.md#153-class-members)) with the differences and restrictions for interfaces:
This subclause augments the description of members in classes ([§15.3](classes.md#153-class-members)) with the differences and restrictions for interfaces:

- A *finalizer_declaration* is not allowed.
- Instance constructors, *constructor_declaration*s, are not allowed.
- All interface members implicitly have public access; however, an explicit access modifier ([§7.5.2](basic-concepts.md#752-declared-accessibility)) is permitted except on static constructors ([§15.12](classes.md#1512-static-constructors)).
- The `abstract` modifier is implied for interface function members ([§12.6](expressions.md#126-function-members)) without bodies; that modifier may be given explicitly.
- An interface instance function member whose declaration includes a body is an implicitly `virtual` member unless the `sealed` or `private` modifier is used. The `virtual` modifier may be given explicitly.
- The `abstract` modifier is implied for interface instance function members ([§12.6](expressions.md#126-function-members)) without bodies; that modifier may be given explicitly. For interface static function members without bodies the `abstract` modifier shall be present.
- An interface instance function member whose declaration includes a body is an implicitly `virtual` member unless the `sealed` or `private` modifier is used. The `virtual` modifier may be given explicitly. An interface static member whose declaration includes a body may have a `virtual` modifier.
- A `private` or `sealed` function member of an interface shall have a body.
- A `private` function member shall not have the modifier `sealed`.
- A `private` instance function member shall not have the modifier `sealed`.
- A derived interface may override an abstract or virtual member declared in a base interface.
- An explicitly implemented function member shall not have the modifier `sealed`.

Expand Down Expand Up @@ -429,7 +429,7 @@

### 19.4.4 Interface properties

This clause augments the description of properties in classes [§15.7](classes.md#157-properties) for properties declared in interfaces.
This subclause augments the description of properties in classes [§15.7](classes.md#157-properties) for properties declared in interfaces.

Interface properties are declared using *property_declaration*s ([§15.7.1](classes.md#1571-general)) with the following additional rules:

Expand All @@ -440,25 +440,27 @@
> *Note*: As an interface cannot contain instance fields, an interface property cannot be an instance auto-property, as that would require the declaration of implicit hidden instance fields. *end note*

- The type of an interface property shall be output-safe if there is a get accessor, and shall be input-safe if there is a set or init accessor.
- An interface method declaration that has a block body or expression body as a *method_body* is `virtual`; the `virtual` modifier is not required, but is allowed.
- An instance *property_declaration* that has no implementation is `abstract`; the `abstract` modifier is not required, but is allowed. It is *never* considered to be an automatically implemented property ([§15.7.4](classes.md#1574-automatically-implemented-properties)).
- An interface instance method declaration that has a block body or expression body as a *method_body* is `virtual`; the `virtual` modifier is not required, but is allowed. For a static method the `virtual` modifier is permitted.
- An instance *property_declaration* that has no implementation is `abstract`; the `abstract` modifier is not required, but is allowed. It is *never* considered to be an automatically implemented property ([§15.7.4](classes.md#1574-automatically-implemented-properties)). However, the `abstract` modifier shall be present if a static property is to be abstract.
- A *property_declaration* may contain the `sealed` modifier.

### 19.4.5 Interface events

This clause augments the description of events in classes [§15.8](classes.md#158-events) for events declared in interfaces.
This subclause augments the description of events in classes [§15.8](classes.md#158-events) for events declared in interfaces.

Interface events are declared using *event_declaration*s ([§15.8.1](classes.md#1581-general)), with the following additional rules:

- *event_modifier* shall not include `override`.
- A derived interface may implement an abstract interface event declared in a base interface ([§15.8.5](classes.md#1585-virtual-sealed-override-and-abstract-accessors)).
- It is a compile-time error for *variable_declarators* in an instance *event_declaration* to contain any *variable_initializer*s.
- An instance event with the `virtual` or `sealed` modifiers must declare accessors. It is *never* considered to be an automatically implemented field-like event ([§15.8.2](classes.md#1582-field-like-events)).
- An instance event with the `abstract` modifier must not declare accessors.
- An instance event with the `virtual` or `sealed` modifiers shall declare accessors. It is *never* considered to be an automatically implemented field-like event ([§15.8.2](classes.md#1582-field-like-events)).
- An instance event with the `abstract` modifier shall not declare accessors.
- A static event may have `abstract`, `virtual`, and `sealed` modifiers.
- The type of an interface event shall be input-safe.

### 19.4.6 Interface indexers

This clause augments the description of indexers in classes [§15.9](classes.md#159-indexers) for indexers declared in interfaces.
This sub clause augments the description of indexers in classes [§15.9](classes.md#159-indexers) for indexers declared in interfaces.

Interface indexers are declared using *indexer_declaration*s ([§15.9](classes.md#159-indexers)), with the following additional rules:

Expand All @@ -474,15 +476,20 @@

### 19.4.7 Interface operators

This clause augments the description of *operator_declaration* members in classes [§15.10](classes.md#1510-operators) for operators declared in interfaces.
This subclause augments the description of *operator_declaration* members in classes [§15.10](classes.md#1510-operators) for operators declared in interfaces.

For an *operator_declaration* in an interface the *operator_body* shall only be a block body ([§15.6.1](classes.md#1561-general)) or an expression body ([§15.6.1](classes.md#1561-general)).

It is a compile-time error for an interface to declare a conversion, equality, or inequality operator.
A static *operator_declaration* may have `abstract`, `virtual`, and `sealed` modifiers.

In the context of a class or struct, at least one of the *fixed_parameter*s in a *unary_operator_declarator* and *binary_operator_declarator* is required to have type `T` or `T?`, where `T` is the instance type of the enclosing type. This requirement is relaxed in the context of an interface in that a restricted operand is allowed to be of a type parameter that counts as “the instance type of the enclosing type.” In order for a type parameter `T` to count as that it shall meet the following requirements:

- `T` is a direct type parameter on the interface in which the operator declaration occurs, and
- `T` is directly constrained by the instance type; i.e., the surrounding interface with its own type parameters used as type arguments.

### 19.4.8 Interface static constructors

This clause augments the description of static constructors in classes [§15.12](classes.md#1512-static-constructors) for static constructors declared in interfaces.
This subclause augments the description of static constructors in classes [§15.12](classes.md#1512-static-constructors) for static constructors declared in interfaces.

The static constructor for a closed ([§8.4.3](types.md#843-open-and-closed-types)) interface executes at most once in a given application domain. The execution of a static constructor is triggered by the first of the following actions to occur within an application domain:

Expand All @@ -498,7 +505,7 @@

### 19.4.9 Interface nested types

This clause augments the description of nested types in classes [§15.3.9](classes.md#1539-nested-types) for nested types declared in interfaces.
This subclause augments the description of nested types in classes [§15.3.9](classes.md#1539-nested-types) for nested types declared in interfaces.

It is an error to declare a class type, struct type, or enum type within the scope of a type parameter that was declared with a *variance_annotation* ([§19.2.3.1](interfaces.md#19231-general)).

Expand All @@ -507,7 +514,7 @@
> <!-- Example: {template:"standalone-lib-without-using", name:"InterfaceNestedTypes", expectedErrors:["CS8427"]} -->
> ```csharp
> interface IOuter<out T>
> {

Check warning on line 517 in standard/interfaces.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/interfaces.md#L517

MDC032::Line length 86 > maximum 81
> class C { } // error: class declaration within scope of variant type parameter 'T'
> }
> ```
Expand Down Expand Up @@ -949,6 +956,8 @@
>
> *end example*

An explicit interface member implementation that implements a static member shall itself be static.

### 19.6.3 Uniqueness of implemented interfaces

The interfaces implemented by a generic type declaration shall remain unique for all possible constructed types. Without this rule, it would be impossible to determine the correct method to call for certain constructed types.
Expand Down
Loading
Loading