Add LDM notes for Feb. 12, 2020
This commit is contained in:
parent
b090ab8413
commit
99094464ff
116
meetings/2020/LDM-2020-02-12.md
Normal file
116
meetings/2020/LDM-2020-02-12.md
Normal file
|
@ -0,0 +1,116 @@
|
|||
|
||||
# C# Language Design for Feb 12, 2020
|
||||
|
||||
## Agenda
|
||||
|
||||
Records
|
||||
|
||||
## Discussion
|
||||
|
||||
### Value equality
|
||||
|
||||
Proposal: use the `key` keyword previously mentioned, but also
|
||||
require it on the type declaration as well, e.g.
|
||||
|
||||
```C#
|
||||
key class HasValueEquality
|
||||
{
|
||||
public key int X { get; }
|
||||
}
|
||||
```
|
||||
|
||||
There are a number of things we could pivot on
|
||||
|
||||
```C#
|
||||
key class HasValueEquality1 { public key int X { get; } }
|
||||
class HasValueEquality2 { public key int X { get; } }
|
||||
key class HasValueEquality3 { public key X { get; } }
|
||||
class HasValueEquality4 : IEquatable<HasValueEquality4> { public int X { get; } }
|
||||
```
|
||||
|
||||
----
|
||||
|
||||
```C#
|
||||
record Point1(int X); // Implies value equality over X
|
||||
record Point2a(int X); // Implies inherited equality
|
||||
key record Point2b1(int X); // Implies value equality over X
|
||||
key record Point2b2a(int X); // Implies "empty" value equality
|
||||
key record Point2b2b(key int X); // Implies value equality over X
|
||||
|
||||
|
||||
key class Point3a(int X); // implies record + value equality over X
|
||||
data class Point3b(int X); // implies record with inherited equality
|
||||
```
|
||||
|
||||
#### Equality default
|
||||
|
||||
We originally considered adding value equality on records both because it's difficult to
|
||||
implement yourself and it fits the semantics we built for records in general. We want to validate
|
||||
that these things are still true, and new considerations, namely whether it is the appropriate
|
||||
default for records and whether it should be available to other types, like regular classes.
|
||||
|
||||
We left off in the previous discussion asking whether value equality is not just
|
||||
an inconvenient default, but actively harmful for key scenarios for records. Some examples
|
||||
we came up with are either classes with large numbers of members, where value equality may
|
||||
be unnecessary and slow, and circular graphs, where using value equality could cause
|
||||
infinite recursion.
|
||||
|
||||
These do seem bad, but it's not obvious that these scenarios either fit perfectly with the
|
||||
canonical record, or if the consequences are necessarily worse than default reference equality.
|
||||
Certainly producing infinite recursion in object graphs is bad, but silently incorrect behavior
|
||||
due to inaccurate reference equality is also harmful, in the same sense. It's also easier
|
||||
to switch from value equality to reference equality than it is to switch from reference equality
|
||||
to value equality, due to the complex requirements in a value equality contract.
|
||||
|
||||
**Conclusion**
|
||||
|
||||
Value equality seems a reasonable default, as long as they are immutable by default, and that
|
||||
there is a reasonable way to opt-in to a different equality.
|
||||
|
||||
#### Separable value equality
|
||||
|
||||
Given that we like value equality as a default, we have to decide if we want a separable equality
|
||||
feature as well. This is important for the scenario:
|
||||
|
||||
```C#
|
||||
record Point1(int X)
|
||||
{
|
||||
public int X { get; }
|
||||
}
|
||||
```
|
||||
|
||||
if there's a separate `key` feature, we need to decide if the substituted property should
|
||||
require, allow, or disallow the `key` modifier, e.g.
|
||||
|
||||
```C#
|
||||
record Point1(int X)
|
||||
{
|
||||
public key int X { get; }
|
||||
}
|
||||
```
|
||||
|
||||
We also need to decide what such a "separable" equality feature would look like, and if it has a
|
||||
difference between records and other classes. We could add a `key` feature for non-records, and
|
||||
disallow `key` entirely in records. The members of a record equality would then not be
|
||||
customizable.
|
||||
|
||||
The individual `key` modifiers on non-records seem deceptively complicated.
|
||||
|
||||
A common case is "opt-in everything". `key` modifiers wouldn't improve much on this, as they
|
||||
would be necessary on every element. On the other hand, there are often computed properties that
|
||||
may be seen as part of "everything", but not part of the equality inputs. The plus of record
|
||||
primary constructors is that they identify the "core" inputs to the type.
|
||||
|
||||
Individual `key` modifiers also do not help with the large custom classes that are written today
|
||||
where it's easy to forget to add new members to equality. With a `key` modifier you can still
|
||||
forget to add the modifier to a new member.
|
||||
|
||||
These decisions play into records as a whole because they affect the uniformity of record and
|
||||
non-record behavior. If records are defined by their "parameters", namely in this syntax the
|
||||
primary constructor parameters and identically named properties, then no other members should
|
||||
be a part of the equality. However, that would imply members in the body are not automatically
|
||||
included. For regular classes, it seems backwards. Members are not generally included, they have
|
||||
to be added specifically.
|
||||
|
||||
On the other hand, if we prioritize uniformity, general members in record bodies would be included
|
||||
in equality, which would harm a view of records as consisting primarily of the "record inputs."
|
|
@ -26,14 +26,6 @@
|
|||
- https://github.com/dotnet/csharplang/issues/3213 Natural value equality (Mads)
|
||||
- https://github.com/dotnet/csharplang/issues/3137 Records (Mads)
|
||||
|
||||
## Feb 12
|
||||
|
||||
- https://github.com/dotnet/csharplang/issues/3137 Records (Mads)
|
||||
|
||||
## Feb 10
|
||||
|
||||
- https://github.com/dotnet/csharplang/issues/3137 Records (Mads)
|
||||
|
||||
## Jan 29, 2020
|
||||
|
||||
- Records: drilling in to individual features (Mads)
|
||||
|
@ -46,6 +38,18 @@
|
|||
|
||||
Overview of meetings and agendas for 2020
|
||||
|
||||
## Feb 12
|
||||
|
||||
[C# Language Design Notes for Feb. 12, 2020](LDM-2020-02-12.md)
|
||||
|
||||
Records
|
||||
|
||||
## Feb 10
|
||||
|
||||
[C# Language Design Notes for Feb. 10, 2020](LDM-2020-02-10.md)
|
||||
|
||||
Records
|
||||
|
||||
## Feb 5
|
||||
|
||||
[C# Language Design Notes for Feb. 5, 2020](LDM-2020-02-05.md)
|
||||
|
|
Loading…
Reference in a new issue