meetings/2020/LDM-2020-04-06.md
Init-only members
We have a proposal to dive into: https://github.com/jaredpar/csharplang/blob/init/proposals/init.md
The proposal notes that you can set init fields of the base type during construction, similar
to readonly. This is not how readonly works today, only the declaring type can set readonly
fields
The proposal allows init on class and struct declarations as a shorthand for init on types.
This is different from how readonly struct works today, where there is no syntactic shorthand,
readonly simply adds the additional requirement that all instance fields are marked readonly.
For the runtime: does this feature prohibit runtime restrictions on setting readonly instance
fields in the future? Put simply: yes. To avoid breaking C#, the runtime would be required to
either respect the proposed InitOnlyAttribute, or restrict optimizations to not alter the code
for these features.
Use in interfaces: the proposal prohibits it, but the following example seems useful:
interface I
{
int Prop { get; init set; }
}
public void MyMethod<T>() where T : I, new()
{
var t = new T() {
Prop = 1
};
}
Signature compatibility: should init properties be compatible with mutable ones? That is, should
removing init in favor of a bare set be binary-compatible? This impacts our decisions for how
we think about safety in older compilers:
If we use a modreq to prevent other compilers from unsafely using a setter, that affects the
signature of the method, and would make the above a breaking change
If we want accept that older compilers are not a problem (C#, VB, and F# will all be updated), perhaps we don't need to specially guard this at all
We could use attributes to mark and guard, by using the Obsolete attribute. ref structs
use this guard by having an Obsolete attribute with a reserved message, that is ignored by
compatible compilers.
Should we allow three accessors: get, set, init? A big problem here is that you can end up
calling instance members in a constructor that invoke the setter, not the initter, for a
property. This means that there are few, if any, invariants that hold for init vs. set, and
weakens the feature significantly.
init vs. initonly for syntax. On the one hand, init is inconsistent with readonly (vs. initonly), but on the other hand we're pretty sad that readonly is such a long keyword. It also has few analogies
with properties, where readonly isn't allowed at all, and the shorter init keyword seems more similar to
get and set
Usage of init as a modifier: there are a number of different meanings here, and similarities
between readonly and init is separating the more places we use it. For instance, if init is
allowed as a member modifier, it seems similar to readonly on members, but they actually do
different things. Moreover, readonly on types means that all instance fields and methods are
readonly, while init on types would only mean init on fields, not on methods.
What are the uses for init methods, aside from helper methods? Could they be used in collection initializers?
The proposal in this doc is that required initialization is also an important feature for setters. We're
going to leave that discussion for a future meeting. As proposed, nullable warnings are not modified for
init members.
Conclusions
No init on types. No agreement on syntax. We probably have to talk about more of the use cases.
We've decided that having three different accessors is not helpful. Settled that we will place a
modreq on all init setters.