csharplang/proposals/records-wip.md

79 lines
3.3 KiB
Markdown
Raw Normal View History

# Records Work-in-Progress
Unlike the other records proposals, this is not a proposal in itself, but a work-in-progress designed to record consensus design
decisions for the records feature. Specification detail will be added as necessary to resolve questions.
The syntax for a record is proposed to be added as follows:
```antlr
class_declaration
: attributes? class_modifiers? 'partial'? 'class' identifier type_parameter_list?
parameter_list? type_parameter_constraints_clauses? class_body
;
struct_declaration
: attributes? struct_modifiers? 'partial'? 'struct' identifier type_parameter_list?
parameter_list? struct_interfaces? type_parameter_constraints_clauses? struct_body
;
class_body
: '{' class_member_declarations? '}'
| ';'
;
struct_body
: '{' struct_members_declarations? '}'
| ';'
;
```
2020-01-03 04:36:27 +01:00
2020-01-03 04:40:04 +01:00
The `attributes` non-terminal will also permit a new contextual attribute, `data`.
A class (struct) declared with a parameter list or `data` modifier is called a record class (record struct), either of which is a record type.
It is an error to declare a record type without both a parameter list and the `data` modifier.
## Members of a record type
In addition to the members declared in the class-body, a record type has the following additional members:
### Primary Constructor
A record type has 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
2020-01-27 21:58:42 +01:00
declared default constructor to be suppressed. It is an error to have a primary constructor and
a constructor with the same signature already present in the class.
At runtime the primary constructor
2020-01-27 21:58:42 +01:00
1. executes the instance field initializers appearing in the class-body; and then
invokes the base class constructor with no arguments.
2020-01-27 21:58:42 +01:00
1. initializes compiler-generated backing fields for the properties corresponding to the value parameters (if these properties are compiler-provided; see [Synthesized properties](#Synthesized Properties))
[ ] TODO: add base call syntax and specification about choosing base constructor through overload resolution
### Properties
2020-01-27 21:58:42 +01:00
For each record parameter of a record type declaration there is a corresponding public property member whose name and type are taken from the value parameter declaration. If no concrete (i.e. non-abstract) property with a get accessor and with this name and type is explicitly declared or inherited, it is produced by the compiler as follows:
2020-01-27 21:58:42 +01:00
For a record struct or a record class:
2020-01-27 21:58:42 +01:00
* A public get-only auto-property is created. Its value is initialized during construction with the value of the corresponding primary constructor parameter. Each "matching" inherited abstract property's get accessor is overridden.
2020-02-29 23:21:55 +01:00
### Equality members
Record types produce synthesized implementations for the following methods:
* `object.GetHashCode()` override, unless it is sealed or user provided
* `object.Equals(object)` override, unless it is sealed or user provided
* `T Equals(T)` method, where `T` is the current type
`T Equals(T)` is specified to perform value equality, comparing the property with same name as
each primary constructor parameter to the corresponding property of the other type.
`object.Equals` performs the equivalent of
```C#
override Equals(object o) => Equals(o as T);
```