2020-11-11 23:23:26 +01:00
|
|
|
# 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)
|
2021-02-04 02:47:44 +01:00
|
|
|
6. [Add `await` as a dotted postfix operator](#add-await-as-a-dotted-postfix-operator)
|
2020-11-11 23:23:26 +01:00
|
|
|
|
|
|
|
## 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
|
|
|
|
|
2020-11-12 00:27:30 +01:00
|
|
|
https://github.com/dotnet/csharplang/issues/1407
|
2020-11-11 23:23:26 +01:00
|
|
|
|
|
|
|
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`.
|
|
|
|
|
2021-02-04 02:47:44 +01:00
|
|
|
#### Add `await` as a dotted postfix operator
|
2020-11-11 23:23:26 +01:00
|
|
|
|
|
|
|
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.
|