
# C# Language Design Meeting for May 27, 2020

## Agenda

1. Records -- syntax

## Discussion

### Syntax Questions

We got significant feedback that `record` is a better name than `data` for indicating
a `record`. There are two syntaxes we've been considering here:

    1. `record class Person { ... }`
    2. `record Person { ... }`

The main difference here is that (2) has less obvious space for a `struct` token, which
raises the question of whether "record structs" are a feature we want to enable.

There are a couple arguments for why records would be useful for structs. The first is
that "value behavior" is a general feature that could be useful for both structs and classes.
Value equality exists for structs today, but it is potentially slow in the runtime implementation.

The second is that the syntax provided for classes is also useful for structs. The positional
syntax specifically seems attractive because it has a lot of similarity to tuples and allows a
form of "named tuple."

```C#
record struct Point(int X, int Y);
```

On the other hand, we could improve the performance of equality, completely separate from records.
For instance, the compiler could add equality methods if they are not present. We also do not necessarily
need to address structs first. Since structs already have many features of records they are, in a sense,
"less far behind" than classes in record features. It makes sense to concentrate first on classes and
consider augmentations for structs in a future update.

So to return to the original question, we have to decide if we want to move forward with option (2), which
is a new form of declaration. Notably, this is a breaking change for certain scenarios e.g.,

```C#
record M(int X, int Y) { ... }

class C
{
    record M(int X, int Y) { ... }
    partial record M(int X, int Y);
}
```

All of these are currently method declaration syntax. In C# 9 this would be a record declaration
with a positional constructor and a body. Normally we would never consider this kind of change,
but since we started shipping with .NET Core we do not automatically upgrade language version
unless the target framework is the newest one (i.e., NET 5).

#### Conclusion

Do not support structs for now. They already support many features of records and we can add
more, time permitting.

The accepted proposal is that the syntax, `<modifiers> <attributes> 'record'` followed by
`identifier` and either '(', '{', or '<' would be contextually parsed as a record declaration
only if the language version is C# 9.

### Short-property syntax

We previously agreed that, to unify the syntax forms in the positional and nominal declaration, we
would allow fields in nominal records with no modifiers to instead be interpreted as public auto-properties.
After looking at feedback and exploring some of the related issues, we've decided that's not the best approach.

There are a few proposals on the table:

    1. Leave positional records the same, do not provide special syntax for nominal records.

```C#
public record Point(int X, int Y);
public record Point
{
    public int X { get; init; }
    public int Y { get; init; }
}
```

    2. Unify the declaration forms in favor of nominal records, allowing property declarations in the
    record parameter list

```C#
public record Point(
    public int X { get; init; },
    public int Y { get; init; }
)
public record Point
{
    public int X { get; init; },
    public int Y { get; init; }
}
```

    3. Keep positional records the same, provide a new modifier (e.g., `data` or `init`) for members
    which means "public init-only property"

```C#
public record Point(int X, int Y);
public record Point
{
    data int X;
    data int Y;
}
```

    4. Provide the new modifier from (3), and require it in both types of records

```C#
public record Point(data int X, data int Y);
public record Point
{
    data int X;
    data int Y;
}
```

After discussion, we prefer (3). Positional records already seem to have enough syntactic distinction and
the `data` keywords seem superfluous in this position. It also makes the shortest syntax form match up
with the most common use case.

However, we do think some further keyword is necessary for nominal records. Looking too much like existing
fields seems like it would be too confusing, especially if we want to also allow fields in records.

Instead, we're considering leaving positional records to generate public auto-properties by default, partly
because they are already a significantly different syntax that cannot be confused with existing language
constructs, and providing a new mechanism for positional records.

#### Conclusion

Keep positional records the same, provide a `data` modifier for fields which means "public
init-only property"

```C#
public record Point(int X, int Y);
public record Point
{
    data int X;
    data int Y;
}
```

