4.0 KiB
C# Language Design Meeting for June 22, 2020
Agenda
-
Data properties
-
Clarifying what's supported in records for C# 9
-
Structs
-
Inheritance with records and classes
-
Discussion
data
properties
We've been working on an implementation for data properties and have some questions about modifiers, which are currently not allowed.
There are some modifiers that could be legal, like new
, abstract
, virtual
, and override
.
Some of these, especially new
and override
would probably prevent data
properties from
being used at all, since a warning would be generated if there's a matching member in the base
that requires either override
or new
.
However, the point of data properties was to be brief. Adding modifiers would potentially cloud the purpose of the feature. The syntactical abbreviation isn't strictly required because the equivalent property can always be written explicitly:
data int X;
// versus
public int X { get; init; }
Conclusion
Based on where we are in the schedule for C# 9, we probably will not have time to respond to feedback.
Therefore, we're planning on putting this feature into preview and not shipping it with C# 9. For now,
let's allow the following modifiers: public
, new
, abstract
, virtual
, and override
. This will
provide an option for allowing data
properties to interact more smoothly with other constructs in C#,
while maintaining some of the simplicity. We'll see how it feels in prototypes to gauge whether we went
too far, or not far enough.
Struct records
We're not sure how much space we have for structs in C# 9, but we do think structs are an
interesting design point. We previously proposed that structs could support a variety of record
behaviors without being a record. One idea would be to automatically implement IEquatable<T>
for all structs, but this has a lot of potential negative impact for the runtime and the
ecosystem: effectively every struct would add a large number of members which could seriously
bloat metadata.
An alternative would be to work with the runtime to try to provide a runtime-generated form of
IEquatable<T>
. If it's cheap enough, we may be able to provide IEquatable<T>
for structs as
a as-necessary addition to all structs. However, this is a potentially very large change. Even
small costs could add up, and even small semantic changes could impact someone.
Overall, the modification of arbitrary struct semantics just seems too risky. Something as simple
as testing a struct for an implementation of IEquatable<T>
could be a breaking change, and with
a change this big, it's almost certain to be breaking for someone.
Conclusion
Altering the semantics of all structs as-is is out. We're leaning towards a real "record struct" declaration.
Inheritance between records and classes
We currently have a restriction that records cannot inherit from classes and classes cannot inherit from records. We should confirm that this restriction is acceptable for C# 9.
Conclusion
We definitely see scenarios for expanding this, but we think the restriction is fine for the first version of records. Based on feedback and example scenarios, we can reconsider these restrictions and also the expected semantics.
with
expressions on non-records
This encompasses:
-
Finding some way to define a compatible
Clone
for user-defined classes -
Anonymous types
-
Tuples
Compatibility for Clone
in user-defined classes is the most difficult of these items because it
relies on a new language feature for requiring that a new object is returned from the Clone
method.
Anonymous types are very simple, we can retroactively define them as record types.
Tuples would be simple to special-case in the language, but it's probably more consistent to decide the semantics for struct records first, and then update the definition of System.ValueTuple to support them.
Conclusion
Anonymous types can be updated at any time, everything else should wait until after C# 9.