# C# Language Design Meeting for November 11th, 2020

## Agenda

1. [IsRecord in metadata](#isrecord-in-metadata)
2. [Triage](#triage)
    1. [AsyncMethodBuilder](#asyncmethodbuilder)
    2. [Variable declarations under disjunctive patterns](#variable-declarations-under-disjunctive-patterns)
    3. [Direct constructor parameters](#direct-constructor-parameters)
    4. [Always available extension methods](#always-available-extension-methods)
    5. [Allow `nameof` to access instance members from static contexts](#allow-nameof-to-access-instance-members-from-static-contexts)
    6. [Add `await` as a dotted postfix operator](#add-await-as-a-dotted-postfix-operator)

## Quote of the Day

- "Alright, I'm going to make an analogy to social security here."

## Discussion

### IsRecord in metadata

https://github.com/dotnet/csharplang/issues/4121

We discussed a few different ways to tackle this issue, which relates to customers depending on the presence of the `<Clone>$` method
as a way of determining if a type is a `record` or not. First, there are theoretically some ways we could retrofit this method to work
as an identifying characteristic, such as by marking `<Clone>$` methods on non-record types, instead of marking the record types in
some manner. However, this approach would have to square with `struct` records, which may or may not have that special method. We also need
to understand some of the dependent scenarios better: we understand the IDE scenario pretty well, we want to be able to have QuickInfo
and metadata-as-source reflect the way the type was declared. However, we don't have an understanding of the EF scenario, and what it
would want to do for, say, a non-record class that inherits from a record type. Finally, we considered time frames, and came to the
conclusion that the proposed solution would work fine if we wait until C# next to introduce it, and does not require being rushed out the
door to be retconned into C# 9: the proposed solution is backwards compatible, as long as it is introduced at the same time as
class/record cross inheritance.

#### Conclusion

Into the Working Set, we'll consider this issue in conjunction with class/record cross-inheritance.

### Triage

#### AsyncMethodBuilder

https://github.com/dotnet/csharplang/issues/1407

We generally like this proposal, as it solves a real need in the framework while creating a generalized feature that can be plugged into
more libraries. We did have a couple of questions come up:
1. Should we allow this on just the method, or also the type/module level? This seems to be similar to `SkipLocalsInit`, and could be
tedious to rep-specify everywhere.
2. Can this solve `ConfigureAwait`? We don't think so: this controls the method builder, not the meaning of `await`s inside the method,
so while it could potentially change whether a method call returns a task that synchronizes to the thread context by default, it could
only do that for methods defined in your assembly, which would just lead to confusing behavior.

##### Conclusion

Triaged into the Working Set, we'll work through the proposal in a full LDM session soon.

#### Variable declarations under disjunctive patterns

https://github.com/dotnet/csharplang/issues/4018

We like this proposal. There are a couple of open issues/questions that need to be addressed:
1. We need a rule that says when you are allowed to redeclare existing variables. It needs to cover multiple switch case labels, while
also not permitting things declared outside the switch label to be redeclared.
2. How identical do the types need to be? Are nullability differences permitted? ie, are `(object?, object)` and `(object, object?)` the
same for the purposes of this feature? It seems like they may have to be.

##### Conclusion

Triaged into the Working Set. We'll take some time and consider these questions, and we should also consider alternatives at the same time,
such as an `into` pattern that would allow a previously-declared variable to be assigned in a pattern, including ones declared outside a
pattern.

#### Direct constructor parameters

https://github.com/dotnet/csharplang/issues/4024

We discussed this feature during our last look at primary constructors, and our conclusion is that we need to explore the space more fully
with both features in mind. There are concerns about abstraction leaks, particularly with property casing.

##### Conclusion

Triaged into the Working Set, to be considered in conjunction with primary constructors.

#### Always available extension methods

https://github.com/dotnet/csharplang/issues/4029

There was some strong negative reaction to this proposal. However, presented another way it's more interesting: users who use `var` need
to include `using`s they otherwise do not need in order to access these types of extension methods, whereas users who do not use `var`
will already have the relevant `using` in scope, and will thus see these extension methods. These types of methods are also often ways of
working around various C# limitations, such as lack of specialization, and would naturally be defined on the type itself if it was possible.

We are concerned with doing anything in this space with extension everything/roles/type classes on the horizon, as we don't want to change
extension methods in a way that we'd regret with those features.

##### Conclusion

Triaged into the backlog. We'll consider this in conjunction with extension everything.

#### Allow `nameof` to access instance members from static contexts

https://github.com/dotnet/csharplang/issues/4037

There is some feeling that this is basically just a bug in the spec (or is just an area where it's not super clear, and it's a bug in the
implementation). We do think this is generally good: yes, the scenario could just use `string.Length`, but that is not really what the user
intended. They wanted the `Length` property on `P`, and if `P` changes to a different type that no longer has `Length`, there should be an
error there. Without this, the cliff that `nameof` tries to solve is just moved further, not removed.

##### Conclusion

Triaged into Any Time. We'd accept a community contribution here: it needs to only permit exactly this scenario, not allow any new types of
expressions in `nameof`.

#### Add `await` as a dotted postfix operator

https://github.com/dotnet/csharplang/issues/4076

The LDT has very mixed reactions on this. While we are sympathetic to the desire to make awaits more chainable, and the `.` can be viewed
as the pipeline operator of the OO world, we don't think this solves enough to make it worth it. Chainability of `await` expressions
isn't the largest issue on our minds with `async` code today: that honor goes to `ConfigureAwait`, which this does not solve. We could go
a step further with this form by making it a general function that would allow `true`/`false` parameters to control the thread context
behavior, but given our mixed reaction to the syntax form as a whole we're not optimistic about the approach. A more general approach that
simplified chaining generally for prefix operators would be more interesting.

##### Conclusion

Rejected. We do like the space of improving `await`, but we don't think this is the way.
