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
2 changes: 1 addition & 1 deletion standard/attributes.md
Original file line number Diff line number Diff line change
Expand Up @@ -806,7 +806,7 @@ When an optional parameter is annotated with one of the caller-info attributes,

Caller-info attributes can occur on optional parameters anywhere, including in delegate declarations. However, the specific caller-info attributes have restrictions on the types of the parameters they can attribute, so that there will always be an implicit conversion from a substituted value to the parameter type.

It is an error to have the same caller-info attribute on a parameter of both the defining and implementing part of a partial method declaration. Only caller-info attributes in the defining part are applied, whereas caller-info attributes occurring only in the implementing part are ignored.
It is an error to have the same caller-info attribute on a parameter of both the defining and implementing part of a partial method or partial indexer declaration. Only caller-info attributes in the defining part are applied, whereas caller-info attributes occurring only in the implementing part are ignored.

Caller information does not affect overload resolution. As the attributed optional parameters are still omitted from the source code of the caller, overload resolution ignores those parameters in the same way it ignores other omitted optional parameters ([§12.6.4](expressions.md#1264-overload-resolution)).

Expand Down
157 changes: 149 additions & 8 deletions standard/classes.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
# 15 Classes

Check warning on line 2 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L2

MDC032::Line length 83 > maximum 81
## 15.1 General

Check warning on line 3 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L3

MDC032::Line length 88 > maximum 81

Check warning on line 3 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L3

MDC032::Line length 91 > maximum 81

Check warning on line 3 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L3

MDC032::Line length 91 > maximum 81

A class is a data structure that may contain 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 a ***derived class*** can extend and specialize a ***base class***.

Check warning on line 6 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L6

MDC032::Line length 83 > maximum 81
Structs ([§16](structs.md#16-structs)) and interfaces ([§19](interfaces.md#19-interfaces)) have members similar to classes but with certain restrictions. This clause defines the declarations for classes and class members. The clauses for structs and interfaces define the restrictions for those types in terms of the corresponding declarations in class types.

## 15.2 Class declarations

Check warning on line 9 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L9

MDC032::Line length 97 > maximum 81

Check warning on line 10 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L10

MDC032::Line length 83 > maximum 81
### 15.2.1 General

Check warning on line 12 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L12

MDC032::Line length 87 > maximum 81
A *class_declaration* is a *type_declaration* ([§14.8](namespaces.md#148-type-declarations)) that declares a new class.

```ANTLR
class_declaration

Check warning on line 16 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L16

MDC032::Line length 86 > maximum 81
: non_record_class_declaration
| record_class_declaration

Check warning on line 18 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L18

MDC032::Line length 84 > maximum 81
;

Check warning on line 20 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L20

MDC032::Line length 82 > maximum 81
non_record_class_declaration

Check warning on line 21 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L21

MDC032::Line length 93 > maximum 81
: non_record_class_without_positional_members
| non_record_class_with_positional_members
;
Expand All @@ -27,7 +27,7 @@
: attributes? class_modifier* 'partial'? 'class' identifier
type_parameter_list? class_base?
type_parameter_constraints_clause* class_body
;

Check warning on line 30 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L30

MDC032::Line length 115 > maximum 81

non_record_class_with_positional_members
: attributes? class_modifier* 'partial'? 'class' identifier
Expand All @@ -36,8 +36,8 @@
;
```

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).

Check warning on line 39 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L39

MDC032::Line length 108 > maximum 81

Check warning on line 40 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L40

MDC032::Line length 82 > maximum 81

Check warning on line 40 in standard/classes.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/classes.md#L40

MDC032::Line length 86 > maximum 81
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)).
Expand Down Expand Up @@ -822,7 +822,7 @@

### 15.2.7 Partial type declarations

The modifier `partial` is used when defining a class, struct, or interface type in multiple parts. The `partial` modifier is a contextual keyword ([§6.4.4](lexical-structure.md#644-keywords)) and has special meaning in a *class_declaration*, a *struct_declaration*, or an *interface_declaration*. (A partial type may contain partial method declarations ([§15.6.9](classes.md#1569-partial-methods)).
The modifier `partial` is used when defining a class, struct, or interface type in multiple parts. The `partial` modifier is a contextual keyword ([§6.4.4](lexical-structure.md#644-keywords)) and has special meaning in a *class_declaration*, a *struct_declaration*, or an *interface_declaration*. (A partial type may contain partial method declarations ([§15.6.9](classes.md#1569-partial-methods)), partial property declarations (§partial-properties), and partial indexer declarations (§partial-indexers)).

Each part of a ***partial type*** declaration shall include a `partial` modifier and shall be declared in the same namespace or containing type as the other parts. The `partial` modifier indicates that additional parts of the type declaration might exist elsewhere, but the existence of such additional parts is not a requirement; it is valid for the only declaration of a type to include the `partial` modifier. It is valid for only one declaration of a partial type to include the base class or implemented interfaces. However, all declarations of a base class or implemented interfaces shall match, including the nullability of any specified type arguments.

Expand Down Expand Up @@ -3493,8 +3493,8 @@

```ANTLR
property_declaration
: attributes? property_modifier* type member_name property_body
| attributes? property_modifier* ref_kind type member_name ref_property_body
: attributes? property_modifier* 'partial'? type member_name property_body
| attributes? property_modifier* 'partial'? ref_kind type member_name ref_property_body
;

property_modifier
Expand Down Expand Up @@ -3531,7 +3531,7 @@

*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.8.11](structs.md#16811-properties)). However, a partial property (§partial-properties) shall not have an `abstract` modifier.

- 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.
Expand Down Expand Up @@ -4174,7 +4174,7 @@

### 15.7.4 Automatically implemented properties

An automatically implemented property (or auto-property for short), is a non-abstract, non-extern, non-ref-valued property with semicolon-only *accessor_body*s. An auto-property shall have a get accessor and may optionally have a set or init accessor.
An automatically implemented property (or auto-property for short), is a non-abstract, non-extern, non-partial, non-ref-valued property with semicolon-only *accessor_body*s. An auto-property shall have a get accessor and may optionally have a set or init accessor.

When a property is specified as an automatically implemented property, a hidden backing field is automatically available for the property, and the accessors are implemented to read from and write to that backing field. The hidden backing field is inaccessible, it can be read and written only through the automatically implemented property accessors, even within the containing type. If the auto-property has no set or init accessor, the backing field is considered `readonly` ([§15.5.3](classes.md#1553-readonly-fields)). Just like a `readonly` field, a read-only auto-property may also be assigned to in the body of a constructor of the enclosing class. Such an assignment assigns directly to the read-only backing field of the property. If the auto-property has an init accessor, the backing field may be assigned to during the construction phase of an object ([§15.7.3.3](classes.md#15733-init-accessors)).

Expand Down Expand Up @@ -4511,6 +4511,93 @@
>
> *end example*

### §partial-properties Partial properties

When a *property_declaration* includes `partial`, that property is said to be a ***partial property***. Partial properties may only be declared as members of partial types ([§15.2.7](classes.md#1527-partial-type-declarations)).

Partial properties may be defined in one part of a type declaration and implemented in another, or be defined and implemented in the same part.

There are two kinds of partial property declarations: If the body of each of the property’s accessors is a semicolon and the property has no `extern` modifier, the declaration is said to be a ***defining partial property declaration***. Otherwise, the declaration is said to be an ***implementing partial property declaration***.

*Note*: As the syntactic form of a property with semicolon accessor bodies is reserved for a defining partial declaration, a partial property cannot be automatically implemented ([§15.7.4](classes.md#1574-automatically-implemented-properties)). *end note*

Partial properties are useful for allowing one part of a type declaration to customize the behavior of another part, e.g., one that is generated by a tool.

> *Example*:
>
> <!-- Example: {template:"standalone-lib-without-using", name:"PartialProperties1"} -->
> ```csharp
> // part containing defining partial declarations
> public partial class C
> {
> public partial string Prop1 { get; set; }
> public virtual partial string Prop2 { get; set; }
> }
>
> // part containing implementing partial declarations
> public partial class C
> {
> private string _field = "";
>
> public partial string Prop1 { get => _field; set => _field = value; }
> virtual public partial string Prop2 { set => _field = value; get => _field; }
> }
> ```
>
> *end example*

Across the parts of a type declaration, there shall be only one defining partial property declaration with a given signature, and there shall be only one implementing partial property declaration with a given signature.

The signature-matching requirements are as follows:

1. Type and ref-kind differences between partial property declarations result in a compile-time error.
1. Differences in tuple element names within partial property declarations result in a compile-time error.
1. The property declarations and their accessor declarations shall have the same modifiers, though the modifiers may appear in a different order. However, this does not apply to the `extern` modifier, which may only appear on an implementing partial declaration. In the case of private accessibility on the property, both shall be implicitly private (that is, with no accessibility modifier) or both shall be explicitly `private`. Likewise, the corresponding accessors shall have the same implicit or same explicit accessibilities.
1. All other syntactic differences in the signatures of partial property declarations result in a compile-time warning, with the following exceptions:

- Attribute lists on or within partial property declarations do not need to match. Instead, merging of attributes in corresponding positions is performed in an unspecified order. Duplicates are not removed.
- Nullable context differences do not cause warnings. In other words, a difference where one of the types is nullable-oblivious and the other type is either nullable-annotated or not-nullable-annotated does not result in any warnings.

1. Nullability differences that do not involve oblivious nullability result in warnings. When analyzing an accessor body, the implementation part signature is used. The definition part signature is used when analyzing use sites.

> *Example*:
>
> <!-- Example: {template:"standalone-lib-without-using", name:"PartialProperties2", expectedErrors:["CS8799", "CS9254", "CS9253"]} -->
> ```csharp
> partial class C1
> {
> private string _field;
> public partial string Prop { get; private set; }
>
> // Error: implementation set accessor modifier mismatch
> public partial string Prop { get => _field; set => _field = value; }
> }
>
> partial class C2
> {
> private string _field;
> public partial string Prop { get; init; }
>
> // Error: implementation of 'Prop' must have an init accessor
> public partial string Prop { get => _field; set => _field = value; }
> }
>
> partial class C3
> {
> private string _field;
> public partial string Prop { get; }
>
> // Error: implementation of 'Prop' cannot have a set accessor
> public partial string Prop { get => _field; set => _field = value; }
> }
> ```
>
> *end example*

In *property_declaration*, the identifier `partial` is recognized as a contextual keyword ([§6.4.4](lexical-structure.md#644-keywords)) only if it immediately precedes the property’s type. A partial property cannot explicitly implement interface properties.

Only a defining partial property participates in lookup.

## 15.8 Events

### 15.8.1 General
Expand Down Expand Up @@ -4804,8 +4891,8 @@

```ANTLR
indexer_declaration
: attributes? indexer_modifier* indexer_declarator indexer_body
| attributes? indexer_modifier* ref_kind indexer_declarator ref_indexer_body
: attributes? indexer_modifier* 'partial'? indexer_declarator indexer_body
| attributes? indexer_modifier* 'partial'? ref_kind indexer_declarator ref_indexer_body
;

indexer_modifier
Expand Down Expand Up @@ -4841,7 +4928,7 @@

*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.13](structs.md#16813-indexers)).
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.13](structs.md#16813-indexers)). However, a partial indexer (§partial-indexers) shall not have an `abstract` modifier.

- 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.
Expand Down Expand Up @@ -5026,6 +5113,60 @@

This replacing of property/properties with indexer/indexers when reading [§15.7.3](classes.md#1573-accessors), [§15.7.5](classes.md#1575-accessibility) and [§15.7.6](classes.md#1576-virtual-sealed-override-and-abstract-accessors) applies to defined terms as well. Specifically, *read-write property* becomes ***read-write indexer***, *read-init property* becomes ***read-init indexer***, *read-only property* becomes ***read-only indexer***, and *write-only property* becomes ***write-only indexer***, and *init-only property* becomes ***init-only indexer***.

### §partial-indexers Partial indexers

When an *indexer_declaration* includes `partial`, that indexer is said to be a ***partial indexer***. Partial indexers may only be declared as members of partial types ([§15.2.7](classes.md#1527-partial-type-declarations)).

Partial indexers may be defined in one part of a type declaration and implemented in another, or be defined and implemented in the same part.

There are two kinds of partial indexer declarations: If the body of each of the indexer’s accessors is a semicolon and the indexer has no `extern` modifier, the declaration is said to be a ***defining partial indexer declaration***. Otherwise, the declaration is said to be an ***implementing partial indexer declaration***.

Partial indexers are useful for allowing one part of a type declaration to customize the behavior of another part, e.g., one that is generated by a tool.

> *Example*:
>
> <!-- Example: {template:"standalone-lib-without-using", name:"PartialIndexers1", ignoredWarnings:["CS1066"]} -->
> ```csharp
> // part containing defining partial indexer declaration
> public partial class C
> {
> public partial int this[int x] { get; private set; }
> }
>
> // part containing implementing partial indexer declaration
> public partial class C
> {
> private int[] _store = new int[100];
> public partial int this[int x = 10] // default argument value is ignored
> {
> get => this._store[x];
> private set => this._store[x] = value;
> }
> }
> ```
>
> *end example*

Across the parts of a type declaration, there shall be only one defining partial indexer declaration with a given signature, and there shall be only one implementing partial indexer declaration with a given signature.

The signature-matching requirements are as follows:

1. Type and ref-kind differences between partial indexer declarations result in a compile-time error.
1. Differences in tuple element names within partial indexer declarations result in a compile-time error.
1. The property declarations and their accessor declarations shall have the same modifiers, though the modifiers may appear in a different order. However, this does not apply to the `extern` modifier, which may only appear on an implementing partial declaration. In the case of private accessibility on the indexer, both shall be implicitly private (that is, with no accessibility modifier) or both shall be explicitly `private`. Likewise, the corresponding accessors shall have the same implicit or same explicit accessibilities.
1. All other syntactic differences in the signatures of partial property declarations result in a compile-time warning, with the following exceptions:

- Attribute lists on or within partial indexer declarations do not need to match. Instead, merging of attributes in corresponding positions is performed in an unspecified order. Duplicates are not removed.
- Nullable context differences do not cause warnings. In other words, a difference where one of the types is nullable-oblivious and the other type is either nullable-annotated or not-nullable-annotated does not result in any warnings.
- Default argument values need not match, and any default arguments values in the implementing partial indexer declaration are ignored.

1. A warning is reported when parameter names differ across defining and implementing declarations. The parameter names from the definition part are used at use sites.
1. Nullability differences that do not involve oblivious nullability result in warnings. When analyzing an accessor body, the implementation part signature is used. The definition part signature is used when analyzing use sites.

In *indexer_declaration*, the identifier `partial` is recognized as a contextual keyword ([§6.4.4](lexical-structure.md#644-keywords)) only if it immediately precedes the indexer’s type. A partial indexer cannot explicitly implement interface indexers.

Only a defining partial indexer participates in lookup.

## 15.10 Operators

### 15.10.1 General
Expand Down
Loading
Loading