Add LDM notes for 2020-05-11
This commit is contained in:
parent
125539b88d
commit
751ebd4669
107
meetings/2020/LDM-2020-05-11.md
Normal file
107
meetings/2020/LDM-2020-05-11.md
Normal file
|
@ -0,0 +1,107 @@
|
|||
|
||||
# C# Language Design Meeting for May 11, 2020
|
||||
|
||||
## Agenda
|
||||
|
||||
Records
|
||||
|
||||
## Discussion
|
||||
|
||||
Today we tried to resolve some of the biggest questions about records,
|
||||
namely how to unify the semantics of nominal records and positional
|
||||
records, and what are the key scenarios that we are trying to resolve
|
||||
with records.
|
||||
|
||||
The main inconsistency is that the members `record class Person(string FirstName, string
|
||||
LastName)` are very different from the members in `class Person(string firstName, string
|
||||
lastName)`. One way of resolving this is to unify the meaning of the declaration in the direction
|
||||
of primary constructors. In this variant, the parameters of a primary constructor always capture
|
||||
items by default.
|
||||
|
||||
To produce public init-only properties like we were exploring, we would require an extra
|
||||
keyword, `data`, that could be generalizable. So a record which has two public init-only
|
||||
members would be written
|
||||
|
||||
```C#
|
||||
record Person(data string FirstName, data string LastName);
|
||||
```
|
||||
|
||||
This would allow a generalizable `data` keyword that could be applied even in regular
|
||||
classes, e.g.
|
||||
|
||||
```C#
|
||||
class Person
|
||||
{
|
||||
data string FirstName;
|
||||
data string LastName;
|
||||
public Person(string first, string last)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The worry here is that we're harming an essential motivation for records, namely a short syntax
|
||||
for immutable data types. In the above syntax, `record` alone does not mean immutable data type,
|
||||
but instead only value equality and non-destructive mutation. A problem with this is that value
|
||||
equality is dangerous for mutable classes, since the hash code can change after being added to a
|
||||
dictionary. This was why we were previously cautious about adding a general feature for value
|
||||
equality. One option to discourage misuse would be to provide a warning for any non-immutable
|
||||
member in a record class.
|
||||
|
||||
The other problem is, frankly, it's not that short. Aside from some duplication of intent by
|
||||
requiring both `record` and `data` modifiers, it also requires applying the `data` modifier to
|
||||
each member, so the overhead grows larger as the type does.
|
||||
|
||||
Alternatively, we could go in the complete opposite direction: limit customizability by making
|
||||
records all about public immutable data.
|
||||
|
||||
For instance, nominal records could also have syntax abbreviation
|
||||
|
||||
```C#
|
||||
record Person { string FirstName; string LastName; }
|
||||
```
|
||||
|
||||
and we could avoid confusion by prohibiting other members entirely.
|
||||
|
||||
This would look at lot more like positional records, e.g.
|
||||
|
||||
```C#
|
||||
record Person(string FirstName, string LastName);
|
||||
```
|
||||
|
||||
and we could introduce further restrictions on those by also disallowing other members
|
||||
in the body, or even disallowing primary constructors entirely.
|
||||
|
||||
Disallowing all members inside of records is draconian, but not entirely without precedence.
|
||||
Enums work the same way in C# and members are added via extensions methods. That's not a ringing
|
||||
endorsement since we've considered proposals for allowing members in enums before, but it also
|
||||
doesn't put it outside the realm of possibility for C#, especially in earlier forms.
|
||||
|
||||
The main drawback of the simplest form is the risk that we might have trouble evolving the
|
||||
feature to fit all circumstances. If we wanted to allow a user to define private fields, the
|
||||
syntax with no accessibility modifier now means "public init-only property" so we might not
|
||||
be able to add support for private fields at all, or we might have to use a syntactic distinction
|
||||
that requires a `private` accessibility, which is a subtle change.
|
||||
|
||||
### Conclusion
|
||||
|
||||
We largely prefer the short syntax for records. A nominal record would look like
|
||||
|
||||
```C#
|
||||
record class Person { string FirstName; string LastName; }
|
||||
```
|
||||
|
||||
This would create a class with public `init-only` properties named `FirstName`
|
||||
and `LastName`, along with equality and non-destructive mutation methods.
|
||||
|
||||
Similarly,
|
||||
|
||||
```C#
|
||||
record class Person(string FirstName, string LastName);
|
||||
```
|
||||
|
||||
would create a class with all of the above, but also a constructor and Deconstruct.
|
||||
|
||||
We have yet to confirm whether `record` disallows private fields entirely, or if it
|
||||
just changes the default accessibility.
|
|
@ -41,10 +41,6 @@
|
|||
|
||||
- https://github.com/jaredpar/csharplang/blob/record/proposals/recordsv3.md clone-style records (Jared)
|
||||
|
||||
## March 11, 2020
|
||||
|
||||
- Records design (Mads, Andy)
|
||||
|
||||
## Jan 29, 2020
|
||||
|
||||
- Records: drilling in to individual features (Mads)
|
||||
|
@ -57,6 +53,12 @@
|
|||
|
||||
Overview of meetings and agendas for 2020
|
||||
|
||||
## March 11, 2020
|
||||
|
||||
[C# Language Design Notes for May 11, 2020](https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-05-11.md)
|
||||
|
||||
Records
|
||||
|
||||
## May 6, 2020
|
||||
|
||||
[C# Language Design Notes for May 6, 2020](https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-05-06.md)
|
||||
|
|
Loading…
Reference in a new issue