meetings/2022/LDM-2022-01-12.md
fieldFor semi-auto properties, there is a question of where initializers are allowed, and what effect they have when written. Our existing rules are pretty simple:
manually-implemented properties cannot have initializers. Auto-properties can have initializers, and the effect of the initializer is assigning to the backing field.
The field keyword walks a fine line here, sitting squarely between both worlds. We think there's some main issues to solve:
To solve this, we have a few options for restrictions on initializers:
After some discussion, we feel that 3 is a step too far. It could potentially be enabled later, if we can find a set of rules that makes sense and unifies the area, but for the moment we don't have those rules. We also think 1 might be a bit too conservative: part of this feature is easing the cliff between full properties and auto properties. Disallowing initializers when the setter is "trivial" seems like it goes against this desire.
There's also some potential future overlap with property-scoped fields. These fields will, presumably, need to be
accessible in a limited fashion from constructors or other locations that can access type state, in order to initialize them. Lazy<T> backing fields, for example,
will almost certainly need to be initialized with a delegate that references the current type, something that cannot be done from an initializer today. If we need
more granular control for the automatic backing field, we think we can rely on that proposal to allow this control.
We have the following formalized rule for when initializers are permitted:
We have the following rule for when properties can be assigned in the constructor of a type:
Semi-auto properties pose a very interesting challenge for definite assignment in struct types. Today, all fields in a struct type must be fully initialized by any
constructor of that type. Existing auto properties are fine here: the compiler controls the implementation of the set method, and we know that they are not accessing
any instance state other than the backing field, and not exposing this before assignment of all fields are completed. Semi-auto properties, by contrast, can have a
user-implemented set or init method, which has all the power a regular set or init method has. It can access instance state, potentially before some other part
of the instance state has been assigned. Further, there is no way to mention the backing field from outside the property (this being one of the main selling points of
the feature). We see a few potential solutions for this:
this = default before access to semi-auto properties is permitted. This a bitter pill, as property initializers run
before the constructor body. This would mean any property initializers are blown away by the this = default; assignment.default. This would allow skipping initialization of all auto and semi-auto properties,
the former of which is not allowed today. While we think this would work, it introduces inconsistencies between regular fields and backing fields, which is odd, and
there could be some clients that suffer from default initializers for all backing fields (mainly around perf).After some discussion, we're pretty conflicted here. We'll have a small group go and explore these ideas and other potential solutions and come back to the LDM with their findings.
No answers today.
https://github.com/dotnet/csharplang/issues/4665
https://github.com/dotnet/csharplang/issues/4666
https://github.com/dotnet/csharplang/issues/4682
Finally, we took a look at 3 different operator-related enhancements for the generic math scenarios we're targeting for .NET 7/C# 11. We're supportive of all of them,
but the checked operator enhancements are definitely going to be the largest amount of work of the 3. There's new syntax and rules around what things are called when
to be hammered out.
For relaxing shift operator requirements, we think that this rule has served its purpose. It is technically possible, via external libraries, to emulate cout and other
shift operator semantics in C# today, but we don't see people doing this. Relaxing the restrictions will make it easier for those libraries to be written, but the general
patterns for the language have been established at this point.
These proposals are generally approved of. We'll look forward to reviewing the concrete designs soon, particularly around checked.