csharplang/meetings/2020/LDM-2020-06-22.md

4.0 KiB

C# Language Design Meeting for June 22, 2020

Agenda

  1. Data properties

  2. 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:

  1. Finding some way to define a compatible Clone for user-defined classes

  2. Anonymous types

  3. 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.