Add LDM notes for May 4, 2020
This commit is contained in:
parent
36bf39178d
commit
a2d15ae55b
95
meetings/2020/LDM-05-04.md
Normal file
95
meetings/2020/LDM-05-04.md
Normal file
|
@ -0,0 +1,95 @@
|
|||
# C# Language Design for May 4, 2020
|
||||
|
||||
## Agenda
|
||||
|
||||
Design review feedback
|
||||
|
||||
## Discussion
|
||||
|
||||
We had a design review on 2020-04-29 to bring our latest designs to the full review team and get
|
||||
feedback. Today we went over the feedback and how it would affect our design.
|
||||
|
||||
### Final initializers
|
||||
|
||||
- Design review said it was very complicated, when do I use an initializer vs a constructor?
|
||||
|
||||
A possible fix would be to try to run initializers *before* constructors, instead of after. The
|
||||
main problem is that this is not where object initializers (using setters) run today. It would be
|
||||
very distasteful to have `init-only` setters run at a different time from regular setters, and
|
||||
worse to subtly run the setters at a different time just because of the presence of a different
|
||||
`init-only` field.
|
||||
|
||||
This is a difficult piece of feedback to reconcile, because it doesn't present a clear direction.
|
||||
However, we're not sure we need to finish the design for final initializers now. We still think
|
||||
the scenarios are useful, but there are many scenarios which don't rely on those semantics. One
|
||||
of the most important scenarios that we were worried about was how to copy a type that had
|
||||
private fields that should not be copied. One proposal was to write a final initializer which
|
||||
either resets certain fields, or `throw`s if the state is invalid. Our proposed alternative for
|
||||
this situation is to write your own copy constructor, which sets up the appropriate state for the
|
||||
copy.
|
||||
|
||||
However, final initializers do address a significant shortfall in existing scenarios, namely that
|
||||
there's no way to validate a whole object in a property setter (or initter). In that sense we do
|
||||
have many existing issues, separate from our records designs, which would be addressable with the
|
||||
feature. There is also no way to validate an object after a `with` expression since necessarily.
|
||||
|
||||
### Factory methods
|
||||
|
||||
The review team agreed about the necessity of "factory" semantics in the `with` expression, namely
|
||||
that the with expression essentially requires a `virtual` Clone method to work correctly through
|
||||
inheritance, but was not convinced that the feature was generally useful.
|
||||
|
||||
We're also not convinced that it's generally useful, but limiting `with` to only be usable on a
|
||||
record is a significant change from where we were before, where records are currently fully
|
||||
representable as regular classes.
|
||||
|
||||
We need to consider if we are willing to live with this limitation, or need a way of specifying
|
||||
the appropriate `Clone` method in source.
|
||||
|
||||
### Structs as records
|
||||
|
||||
Can every struct be a record automatically? We don't need a `Clone` method, because structs
|
||||
already copy themselves and they already implement value equality (albeit sometimes
|
||||
inefficiently). If we take this stance, would we want to explicitly design records as "struct
|
||||
behavior for classes?" If that's true, we would seek to use the behavior of structs as a template
|
||||
for records.
|
||||
|
||||
### Positional records
|
||||
|
||||
The feedback was negative about making a primary constructor parameters different from positional
|
||||
record parameters. The proposal during the design meeting was that primary constructors would see
|
||||
parameters as "captured" in the scope of the class, while records would generate public
|
||||
properties for each parameter. This is a big semantic divergence, as expressions like
|
||||
`this.parameter` would be legal in the body of a positional record, but illegal in the body of a
|
||||
class with a primary constructor. One way of shrinking the semantic gap would be to always
|
||||
generate members based on primary constructor parameters, but in regular classes those members
|
||||
would be private fields, while in records they would be public init-only properties. Even this
|
||||
semantic difference was perceived as too inconsistent.
|
||||
|
||||
We have two proposals to unify the behavior inside and outside of records. On one end, we could
|
||||
try to view primary constructors as a syntactic space to contain more elements. By default,
|
||||
primary constructors would be simple parameters, which could be closed over in the class body. By
|
||||
allowing member syntax in the parameter list, the user would have more control over the
|
||||
declaration. For instance,
|
||||
|
||||
```C#
|
||||
public class Person(
|
||||
public string Name { get; init; }
|
||||
);
|
||||
```
|
||||
|
||||
would generate a public property named `Name` instead of simply a parameter and the property
|
||||
would be implicitly assigned in the constructor.
|
||||
|
||||
On the other hand, we could _always_ make public properties, abandoning the idea of
|
||||
primary-constructor-parameters-as-closures. In this formulation,
|
||||
|
||||
```C#
|
||||
class C(int X, int Y);
|
||||
```
|
||||
|
||||
would generate two properties, X and Y. If this is made into a record e.g., `data class C(int X,
|
||||
int Y)`, then the same record members would be synthesized as in a nominal record.
|
||||
|
||||
We did not settle on a conclusion, but have a rough sense that having a primary constructor
|
||||
always generate properties is preferred.
|
|
@ -37,10 +37,6 @@
|
|||
- https://github.com/dotnet/roslyn/issues/43147 Open issues in extension `GetEnumerator` (Fred)
|
||||
- https://github.com/dotnet/csharplang/blob/master/proposals/Simple-programs.md Args in top-level programs (Aleksey, Mads)
|
||||
|
||||
## May 4, 2020
|
||||
|
||||
- Record Monday: feedback from design review (Andy, Jared, Mads)
|
||||
|
||||
## April 29, 2020
|
||||
|
||||
- Design review
|
||||
|
@ -69,13 +65,18 @@
|
|||
|
||||
Overview of meetings and agendas for 2020
|
||||
|
||||
## May 4, 2020
|
||||
|
||||
[C# Language Design Notes for May 4, 2020](https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-05-04.md)
|
||||
|
||||
1. Reviewing design review feedback
|
||||
|
||||
## April 27, 2020
|
||||
|
||||
[C# Language Design Notes for April 27, 2020](https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-04-27.md)
|
||||
|
||||
Records: positional & primary constructors
|
||||
|
||||
|
||||
## April 20, 2020
|
||||
|
||||
[C# Language Design Notes for April 20, 2020](https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-04-20.md)
|
||||
|
|
Loading…
Reference in a new issue