# C# Language Design for April 13, 2020

## Agenda

1. Roadmap for records
2. Init-only properties


# Roadmap for records

We want to break down the records feature in a way that gets incremental steps out to partner teams and users sooner, and lets us iterate based on feedback. So what order should we do things in?

Two demanding aspects of records that are certainly important but can probably be done later are:

1. Primary constructors (allowing positional parameters directly on record types)
2. Inheritance to and from record types

So a proposal is to split those off in the first iteration of implementation.

## Decision

We do need to get those right to ultimately ship the feature! However, we want to start by building a version of records that:
* Is nominal only (no primary constructor)
* Inherits from object and can't be inherited from
* Special-cases `with` expressions to `With` methods rather than rely on a "Factory" feature
* Fully implements value equality

For this to be useful we need the init-only property feature at the same time as well, so that there is *some* way to create and initialize immutable records.

In subsequent iterations we will
* Add support for inheritance to records
* Add primary constructors to records
* Generalize the `With` implementation to use factories
* Decide on and embrace defaults (`public` by default?) and abbreviations

On parallel tracks we will work on:
* Factory methods
* Validators?
* Mandatory properties?
* Primary constructors as a general feature?


# Init-only members

Init-only properties are the most urgent separate feature to nail down, as the experience of even the first iteration of records depends on them. There are a couple of design decisions still left open; we address them here.

## Should we have init-only fields? 

Readonly fields today can only be assigned during construction, and only through a `this` access within the body of the class that declares the field. As we extend the concept of "initialization time" to cover execution of init-only setters (by object initializers in client code) as well as validators (if we add those to the language), it makes sense that `readonly` fields should be assignable from within those kinds of members as well.

We would *not* allow readonly fields to be directly assigned in an object initializer, however, as that would undermine the expectation that the class author has full control over how and when they are assigned.

Allowing init-only properties to assign readonly fields would address most of the init-only scenario: An object initializer can be used to set immutable state on the newly created object. A dedicated init-only form of fields is not needed for that. It probably *does* have valid scenarios (in programming styles where immutable fields are themselves public), but those seem less central. We could wait see if that rises to the importance of a seperate, subsequent feature.

### Decision

Let's allow init-only property setters (and validators, if and when we add them) to assign to `readonly` fields of the same object. 

Let's not add init-only fields now. We can consider a new kind of field that can be initialized directly in object initializers later, as a separate feature, if we become convinced that it's worthwhile.

## Syntax

Should the setters of init-only properties be called `init` or `init set`? In other words, is `init` a modifier on the `set` accessor, or does it replace it completely?

Shorter is generally nicer. However, we do foresee a (near?) future where `init` as a modifier could be applied to other members and accessors, to mean that they can only run during initialization (and in return would get privileges such as assigning to readonly members).

### Decision

`init` it is. `init` as a modifier is an interesting feature, but we can discuss it separately. If we do, we can consider allowing `init set` as a long form of an init-only setter for regularity when code has `init` modifiers in multiple places. But for now, let's just allow `init` instead of `set`.

## Init-only indexers

Indexers also have `set` accessors. Should they also be allowed to declare an `init` accessor instead?

### Decision

It makes perfect sense, is somewhat useful, would be more regular in the language, and has straightforward semantics. Let's do it.
