csharplang/meetings/2021/LDM-2021-04-14.md
2021-11-03 10:12:12 -07:00

5.3 KiB

C# Language Design Meeting for April 14th, 2021

Agenda

  1. Shadowing in record types
  2. field keyword
  3. 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:

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 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 Appends would allow arguments after the builder, and bool-returning Appends 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).