# C# Language Design Meeting for April 14th, 2021

## Agenda

1. [Shadowing in record types](#shadowing-in-record-types)
2. [`field` keyword](#field-keyword)
3. [Improved interpolated strings](#improved-interpolated-strings)

## Quote of the Day

- "We're taking my sarcastic suggestion"

## Discussion

### Shadowing in record types

In C# 10, we want to allow the user to change whether a record primary constructor parameter is a property or a field. However, we run into an
issue with currently-legal C# 9 code like this:

```cs
using System;

var c = new C(2);
c.Deconstruct(out var x);
Console.WriteLine(x); // Prints 1

public record Base 
{
    public int X { get; set; } = 1;
}
public record C(int X) : Base
{
    public new int X = X;
}
```

In this example, what will deconstruct refer to? In C# 9, it will be `Base.X`, but if we allow changing whether `X` is a property or not then
C# 10 will consider that to be `C.X`, and the code will print 2. We consider this to a pathological case and not something we intended to enable
in C# 9, so we will take a hard-line approach and patch C# 9 to make shadowing a base record property like this an error.

#### Conclusion

Make this code an error in C# 9. In C# 10, `Deconstruct` will refer to `C.X`.

### `field` keyword

https://github.com/dotnet/csharplang/issues/140

After our [last](LDM-2021-03-24.md#field-keyword) meeting on partially-implemented auto-properties, we had decided to look more deeply at a
few alternate syntaxes to see if we could avoid the need to make `field` a contextual keyword. While some of the suggestions would take less
compiler work, our ultimate conclusion here is that we'd prefer to do the work needed to make `field` a contextual keyword over taking what we
feel is an inferior syntax. As part of this work, we can consider making the public Roslyn APIs around backing fields more consistent. Today,
there are differences between what `GetMembers()` will return for auto-properties vs field-like events, and in order to implement the `field`
keyword we will likely need to take the same strategy as we did with field-like events to avoid circularities. We will also consider standardizing
the behavior here as it has also been a source of Roslyn-API consumer confusion in the past. We will also consider a .NET 6 warning wave to prefix
`field` identifiers in properties that do not correspond to a backing field with either `@` or `this.`, as appropriate.

#### Conclusions

We will proceed with `field` as the keyword, and would like to have .NET 6 warning wave to nudge users to write code that has no chance of being
ambiguous.

### Improved interpolated strings

https://github.com/dotnet/csharplang/issues/4487

Today, we took a look at two questions. First, should we allow interpolated string builders to be passed by ref? And if so, what, if any, is
syntax needed on the builder? We think this will be important for both safety and optimal performance in some framework builders: if the builder
is a struct type and is passed by reference and it captures any reference types as fields, then those fields can be cleared by the called method,
which will help ensure things aren't unnecessarily rooted. We already have a good precedent for this in extension methods: struct types are allowed
to be passed by `ref` as the `this` parameter, and no `ref` is required at the call site. We think the same rules will work here as well.

We also took a look at out-of-order parameter evaluation. Our current proposal is that a builder can be annotated with an
`InterpolatedStringBuilderArgument` attribute, and that the compiler will look at the names in the attribute to determine which parameters to pass
to the `Create` method call of the builder. However, we have a question of what to do if the named parameter is _after_ the interpolated string
literal and the interpolated string is being lowered using the `bool`-returning `Append` methods, as we will have to evaluate the trailing parameter
before the contents of the interpolated string. This would break lexical ordering, which is likely to be extremely confusing and have detrimental
effects on definite assignment, as well as user understanding. However, in order for maximum compatibility with existing API signatures, this would
have to be supported, as there existing API shapes (such as `Utf8Formatter`) that put the location the interpolated string would go before some of
the arguments that the builder will need (in the case of `Utf8Formatter`, their signatures are the value to be formatted, then the destination span).
We could potentially make this dependent on the `Append` calls used the by the builder: `void`-returning `Append`s would allow arguments after the
builder, and `bool`-returning `Append`s would not. This would allow the compiler to evaluate the interpolation holes ahead of time and preserve
lexical ordering. However, it has its own downsides of adding confusion to the builder pattern, and might be more difficult to tool. Further discussion
on this topic revealed that we need to revisit the whole question of conditional execution in order to make a decision here.

#### Conclusion

* Ref parameters are approved, using the same rules as extension method `this` parameters.
* We will take the Monday LDM to resolve the questions around conditional execution and out-of-order parameter execution (and hopefully all other
open questions on this proposal).
