Skip to content

Commit 6e5f1ea

Browse files
RexJaeschkeBillWagner
authored andcommitted
reorg record-related text
1 parent e51b80c commit 6e5f1ea

1 file changed

Lines changed: 56 additions & 21 deletions

File tree

standard/classes.md

Lines changed: 56 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5720,19 +5720,48 @@ It is an error for an instance field of a record class to have an unsafe type.
57205720

57215721
A positional record class (§rec-class-general) has a synthesized primary constructor; see §rec-class-pos-mem-pricon for more information.
57225722

5723+
### §synth-members Synthesized record class members
57235724

5725+
#### §synth-members-general General
57245726

5727+
Certain members are synthesized by the compiler unless a member with a matching signature is declared in the *record_class_body*, or an accessible concrete, non-virtual member with a matching signature is inherited. A matching member prevents the compiler from generating that member only, not any other synthesized members. Two members are considered matching if they have the same signature or would be considered hiding in an inheritance scenario.
57255728

5729+
The synthesized members are described in the following subclauses.
57265730

5727-
## §synth-members Synthesized record class members
5731+
#### §copy-constructor Copy constructors
57285732

5729-
### §synth-members-general General
5733+
A ***copy constructor*** for a type `T` is a constructor having a single parameter of type `T`. The purpose of a copy constructor is to copy the state from the parameter to the new instance being created.
57305734

5731-
Certain members are synthesized by the compiler unless a member with a matching signature is declared in the class body, or an accessible concrete, non-virtual member with a matching signature is inherited. A matching member prevents the compiler from generating that member only, not any other synthesized members. Two members are considered matching if they have the same signature or would be considered hiding in an inheritance scenario.
5735+
> *Example*: Consider the following:
5736+
>
5737+
> <!-- Example: {template:"standalone-lib-without-using", name:"CopyConstructors1"} -->
5738+
> ```csharp
5739+
> class Person
5740+
> {
5741+
> public int Age { get; set; }
5742+
> public string Name { get; set; }
5743+
> public Person(Person aPerson)
5744+
> {
5745+
> Name = aPerson.Name;
5746+
> Age = aPerson.Age;
5747+
> }
5748+
> }
5749+
> ````
5750+
>
5751+
> This declares a mutable, non-record class with two read-write properties, and a user-written copy constructor.
5752+
>
5753+
> In the following case,
5754+
>
5755+
> <!-- Example: {template:"standalone-lib-without-using", name:"CopyConstructors2"} -->
5756+
> ```csharp
5757+
> record Person(int Age, string Name);
5758+
> ````
5759+
>
5760+
> the record class is immutable. The synthesized auto properties `Age` and `Name` are read-init. A copy constructor is synthesized, as is a primary constructor. *end example*
57325761
5733-
The synthesized members are described in the following subclauses.
5762+
In certain circumstances (§rec-class-copyclone), a copy constructor may be synthesized by the compiler, and called by synthesized code.
57345763
5735-
### §rec-class-equalmem Equality members
5764+
#### §rec-class-equalmem Equality members
57365765
57375766
If a record class is derived directly from `object`, the record class type has a synthesized, readonly property equivalent to a property declared as follows:
57385767
@@ -5752,7 +5781,7 @@ The property may be declared explicitly. It is an error if the explicit declarat
57525781

57535782
The record class type implements `System.IEquatable<R>` and includes a synthesized, strongly-typed overload of `Equals(R? other)` where `R` is the record class type. The method is `public`, and the method is `virtual` unless the record class type is `sealed`. The method can be declared explicitly. It is an error if the explicit declaration does not match the expected signature or accessibility, or the explicit declaration doesn't allow overriding in a derived type and the record class type is not `sealed`.
57545783

5755-
If `Equals(R? other)` is user-defined (that is, not synthesized) but `GetHashCode` is not, a warning shall be issued.
5784+
If `Equals(R? other)` is user-defined but `GetHashCode` is not, a warning shall be issued.
57565785

57575786
```csharp
57585787
public virtual bool Equals(R? other);
@@ -5899,7 +5928,7 @@ The synthesized override of `GetHashCode()` returns an `int` result of combining
58995928
>
59005929
> *end example*
59015930
5902-
### §rec-class-copyclone Copy and clone members
5931+
#### §rec-class-copyclone Copy and clone members
59035932
59045933
A record class type contains two copying members:
59055934
@@ -5910,7 +5939,7 @@ The copy constructor shall not execute any instance field/property initializers
59105939
59115940
If a virtual clone method is present in the base record class, the synthesized clone method shall override it, and the return type of the clone method shall be the current containing type if the covariant-returns feature is supported, and the override return type otherwise. It is an error if the base record class clone method is sealed. If a virtual clone method is not present in the base record class, the return type of the clone method shall be the containing type and the method shall be virtual, unless the record class is sealed or abstract. If the containing record class is abstract, the synthesized clone method shall also be abstract. If the clone method is not abstract, it shall return the result of a call to a copy constructor.
59125941
5913-
### §rec-class-prtmem Printing members
5942+
#### §rec-class-prtmem Printing members
59145943
59155944
If a record class is derived directly from `object`, the class includes a synthesized method equivalent to a method declared as follows:
59165945
@@ -6078,20 +6107,20 @@ The synthesized method:
60786107
>
60796108
> *end example*
60806109
6081-
### §rec-class-pos-mem Positional record class members
6110+
#### §rec-class-pos-mem Positional record class members
60826111
6083-
#### §rec-class-pos-mem-gen General
6112+
##### §rec-class-pos-mem-gen General
60846113
60856114
As well as providing the members described in the preceding subclauses, positional record classes ([§15.2.1](classes.md#1521-general)) synthesize additional members with the same conditions as the other members, as described in the following subclauses.
60866115
6087-
#### §rec-class-pos-mem-pricon Primary constructor
6116+
##### §rec-class-pos-mem-pricon Primary constructor
60886117
6089-
A record class type shall have a public constructor whose signature corresponds to the value parameters of the type declaration. This is called the ***primary constructor*** for the type, and causes the implicitly declared default constructor, if present, to be suppressed. It is an error to have a primary constructor and a constructor with the same signature already present in the class.
6118+
A record class type shall have a public constructor whose signature corresponds to the value parameters of the type declaration, if any. This is called the ***primary constructor*** for the type, and causes the implicitly declared default constructor, if present, to be suppressed. It is an error to have a primary constructor and a constructor with the same signature already present in the class.
60906119
60916120
At runtime the primary constructor
60926121
60936122
1. Stores the value of each parameter in the corresponding generated field.
6094-
1. Executes the instance initializers appearing in *record_body*.
6123+
1. Executes the instance initializers appearing in *record_class_body*.
60956124
1. Invokes the base record class constructor with the arguments provided in the *record_base* clause, if present.
60966125
60976126
Each reference to a parameter in user code is replaced with a reference to the corresponding generated field.
@@ -6160,13 +6189,7 @@ A primary constructor parameter is considered to be passed to the base type via
61606189
- The argument represents an implicit or explicit identity conversion of a primary constructor parameter;
61616190
- The argument is not part of an expanded `params` argument;
61626191
6163-
For a primary constructor with an auto-generated field and corresponding property, attributes may be applied to those, as follows:
6164-
6165-
```csharp
6166-
record C([property: Attr1] int X, [field: Attr2] int Y);
6167-
```
6168-
6169-
#### §rec-class-pos-mem-props Properties
6192+
##### §rec-class-pos-mem-props Properties
61706193
61716194
For each parameter of a positional *record_declaration* ([§15.2.1](classes.md#1521-general)) there shall be a corresponding public property member whose name and type are taken from the value parameter declaration.
61726195
@@ -6194,7 +6217,7 @@ For a record class:
61946217
>
61956218
> *end example*
61966219
6197-
#### §rec-class-pos-mem-decon Deconstruct
6220+
##### §rec-class-pos-mem-decon Deconstruct
61986221
61996222
A positional record class ([§15.2.1](classes.md#1521-general)) with at least one parameter causes to be synthesized a public `void`-returning instance method called `Deconstruct` with an out parameter declaration for each parameter of the primary constructor declaration. Each parameter of `Deconstruct` has the same type as the corresponding parameter of the primary constructor declaration. The body of the method assigns to each parameter of `Deconstruct` the value from an instance member access to a member of the same name. The method may be declared explicitly. It is an error if the explicit declaration does not match the expected signature or accessibility, or is static.
62006223
@@ -6223,3 +6246,15 @@ A positional record class ([§15.2.1](classes.md#1521-general)) with at least on
62236246
> ```
62246247
>
62256248
> *end example*
6249+
6250+
## §rec-class-diffs Record class and non-record class differences
6251+
6252+
A record class differs from a non-record class in several important ways:
6253+
6254+
- It is declared using the keyword `record` instead of `class`.
6255+
- It has a number of members generated for it by the implementation, including a copy constructor.
6256+
- Its declaration may contain a *delimited_parameter_list* having zero or more parameters, which results in the generation of a primary constructor having those parameters. For each parameter, the implementation shall provide field-like storage and a property with get and init accessor. A `Deconstruct` method is also provided.
6257+
- If it is derived from other than `object`, it may pass arguments to its base type.
6258+
- Its class body may be omitted.
6259+
- It shall not have a member called `Clone`.
6260+
- It shall not have an instance field with an unsafe type.

0 commit comments

Comments
 (0)