
# C# Language Design Meeting for March 23rd, 2020

## Agenda

1. Triage
2. Builder-based records

## Discussion

### Triage

#### Generic constraint `where T : ref struct`

Proposal: #1148

This is a very complicated area. It's probably not good enough to add this generic constraint,
because things like default interface methods create a boxed `this` parameter. It's likely that
we would need runtime support to make this safe.

This is somwewhat related to the designs in the shapes/roles proposal in that it's about using
the "shape" of an interface, possibly with more restrictions than interfaces themselves. Since
both proposals may require runtime changes it would be valuable to batch up those changes
together.

##### Conclusion

Push to at least C# 10.0. Should be considered in concert with the shapes/roles proposals.

#### Improve overload resolution for delegate compatibility

Proposal: #3277

This is a parallel to changes we previously made to betterness where we remove overloads
that will later be considered invalid, to be removed from the overload resolution candidate
list in the beginning. This functionally will cause more overload resolution calls to succeed,
since invalid candidates will be removed and this will prevent overload resolution ambiguitiy.

##### Conclusion

Tentatively added to C# 9.0. We'd like this proposal for function pointers, so if we were to
implement this for function pointers and correct overload resolution for delegates at the same
time, that would be desirable.

#### Allow GetEnumerator from extension methods

Proposal: #600

First thing is to confirm that there's no compat concern. When we tried to extend the behavior
for `IDisposable` we ran into a problem because `foreach` *conditionally* disposes things which
match the `IDisposable` pattern. This means that if anything starts satisfying the pattern which
didn't before, an existing method may be newly called. If we ever conditionally use the `foreach`
pattern this would probably also be a breaking change.

##### Conclusion

Willing to accept it any time, as long as we confirm that it's not a breaking change.

### Builder-based records

When discussing records we've had various
designs that focus on "nominal" scenarios, where the members of the record are set by name, instead of lowering into method parameters. One proposed implementation strategy is a new series of rules around initialization that we've sometimes called "initonly." We've also looked at using struct "builders" in the past for a similar purpose, and would like to revisit some of these discussions.

We have a proposal from a community member, @HaloFour, that lays out another example implementation strategy that we're using for discussion.

https://gist.github.com/HaloFour/bccd57c5e4f3261862e04404ce45909e

There are certainly some advantages to this structure:

* Uses existing valid C# to implement the pattern, making it compatible with existing compilers. If
we avoid usage of features like `ref struct` and `in`, it could be compatible for even older
consumers, since this would be binary compatible with C# 2.0 metadata.

* Allows the type being built to always see the whole set of property values being initialized,
meaning that the author of the type can validate the new state of the object.

* No new runtime support for any features (e.g., does not require covariant returns)

There are also some disadvantages.

Performance could be a problem. For classes, the biggest concern is stack size. Currently,
initializing a class with an object initializer only requires a single pointer on the class and
then each member is initialized separately, the initializer values don't all need to be on the
stack simultaneously. If we use a struct builder, the entire builder needs to be on the stack
before initialization.

For structs, there is the extra stack space cost, but having a builder also effectively doubles
the metadata size of the every struct. It's also potentially harder for the CLR to optimize the
initialization and remove dead stores through the double-struct passing. If we go forward with
this approach we should consult the JIT for their perspective.

We're also not sure that this approach fully eliminates all brittleness in adding/changing fields
and properties across inheritance, especially if the inheritance is split across assemblies and
only one author is recompiled, or they are recompiled in a different order. If we can find a way
to close those holes, or limit the feature to prevent these situations, that could be an
important mitigating factor.

#### Conclusion

There's a difficult balance here. Some members are focused on about performance, some prioritize
ecosystem compat, and others prioritize "cleanliness" of design, in different directions. Almost
everyone has a different priority and prefers different approaches for different reasons. We need
to discuss things more and reduce some of the unknowns.
