- "I think it's actually a good think to have that onericity. Onericity? I think that's a word I just made up."
We started today by exploring a piece of community feedback on the previous proposal for introducing breaking changes: what if, instead of trying to make field
behave like value
does today, we try
to make it a contextual keyword when in a property accessor? One thing that became clear here, after multiple discussion directions, was that we needed to determine what the most important bit to the LDM
is here: is it most important to the LDM that field
behaves identically to value
(whether that's as a contextual keyword or an implicit parameter), or can we view them as unrelated concepts? We mostly
think the former, but there are some members of the LDM that would prefer to have field
have their desired semantics, even if that means it differs from value
. There is a potential that, by changing
value
, we will break a concept that is understood by a large number of our users. We do hear more about people misunderstanding the meaning of value
than not, but this could simply be a biased opinion
because we only ever hear the complaints.
We then turned to talking about the advantages and disadvantages of using contextual keywords in these scenarios, and how broad we want to make the context. A number of LDM members were happy with the fairly constrained scope of the breaks and fixes here, and think that they end up being fairly straightforward. There are a few interesting wrinkles that need to be worked out:
- What is the behavior of
nameof(value)
? Today, it's the string"value"
,value
is actually a parameter namedvalue
. We didn't arrive at a concrete conclusion on this today. - How does this behave for indexers?
value
is a legal parameter for get-only indexers, does it need to remain so? And does it need to continue to be illegal for settable properties? We also did not arrive at a conclusion for this today.
After discussion, we are most in favor of field
and value
as contextual keywords. We then discussed the scope of this: does every usage of field
and value
within a property need to be escaped, just
the simple names, or somewhere in between? The example we looked at for these is:
int Prop
{
get
{
int field = 1; // If it's only simple names that need to be escaped, this is legal
field = 2; // This needs to be escaped in every version; are we ok with the inconsistency between declaration and usage?
this.field = 3; // This is unambiguous, but does it need to be escaped anyways?
}
}
We ended up with 3 options:
- Only simple names need to be escaped.
int field = 1
is legal, as isthis.field
, butfield = 2
would need to be escaped to refer to the local or class field. - Simple names and declarations need to be escaped.
int field = 1;
needs to be escaped, butthis.field
does not. - All usages need to be escaped. Both
int field = 1;
andthis.field
need to be escaped.
Consistency is again a key point here. Existing contextual keywords, such as await
within an async
method body, must always be escaped, no matter how it's used. this.await
, for example, must be
written as this.@await
. This ultimately convinced us that option 3 is right: if the goal here is to take breaks to make the language simpler, let's not introduce another set of rules around when a
contextual keyword is legal to use unescaped.
We will move forward with the proposal to treat field
and value
as contextual keywords. We will treat them as contextual keywords in all usages within accessor bodies. More work will need to be done
to determine the behavior of indexers, nameof(value)
, and whether value
is a contextual keyword within a get
body.
#7706
https://github.com/dotnet/csharplang/pull/7906/commits/aa6ab11c7df001e807e956f5b056785588e8b12e
Finally today, we took a brief look at the proposal for overload resolution priority. We've previously looked at it in the form of BinaryCompatOnlyAttribute
, but some particularly gnarly challenges
with OHI convinced us that it was not the right approach. Instead, we went with a narrower approach of allowing an API author to adjust the relative priority of their methods to ensure that something
that is better for a given domain, such as the Debug.Assert
overload that takes a CallerArgumentExpressionAttribute
, is preferred over what C# would normally choose. The LDM appreciated the specificity
and narrow target of the new proposal, though there are likely some finer details to work out with where exactly the specification needs to be modified, and how it will interact with extension lookup in
the new extension type world. We also did a quick dive on some of the open questions around inheritance with this new attribute: with the exception of a few things like parameter names and default values,
the original definition of a virtual method is always the one used for determining applicability, and it seems likely that we'd want to do the same here, and not allow derived overrides to change the
priority of a member; we did not concretely decide this, however, so we'll need to confirm when implementation starts.
Proposal is approved, and we'll work on it in the upcoming development cycle.