Back to Csharplang

C# Language Design Meeting for April 13th, 2022

meetings/2022/LDM-2022-04-13.md

latest5.5 KB
Original Source

C# Language Design Meeting for April 13th, 2022

Agenda

Quote of the Day

  • "I think we're just vague about where we become soup"

Discussion

Parameter null checking

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

We're following up to last week's discussion on parameter null checking, deciding on our answers to two questions:

  1. Should we change the syntax of the feature, and if so, what syntax should we choose?
  2. Do we still feel confident in this feature at all?

To think about the first question, we put up some syntax ideas. Some of these have been previously discussed, others arose from community discussion on this feature. We also went through and listed some pros and cons for each syntax form.

  1. void M(string s!!); - The current form
    1. This syntax is perceived as very shouty, which we can understand. It does generalize to an expression form later though, which is nice to think about the future.
  2. void M(string! s);
    1. We dislike putting the modifier on the type, as it implies that ! can be put on types in other locations, and we don't have any idea on how we'd actually enable such a feature in the future. It also negatively affects usage in lambdas, as users would be required to add a type to their lambda declarations to use the feature.
    2. We also considered whether Type! could be used on a local, which would force a null check whenever something is assigned to that local. There was not much support this extension after consideration, however.
  3. void M(string s!);
    1. This is much less shouty, as it's only one ! character. However, we're concerned about confusing all the different meanings of !; for example, the !'s in this example mean different things: x! => x!;.
  4. void M(notnull string s);
    1. A keyword can be more clear, but we're not certain this is. It feels redundant, as the parameter is already declared as not null. It also has a different meaning than the NotNull attribute.
  5. void M(string s ?? throw);
    1. On the one hand, this feels pretty intuitive, as ?? throw is already legal expression syntax (provided there's an exception type on the other side). However, we're concerned with the interaction with default parameters, as string s ?? throw = "" looks very confusing, and string s = "" ?? throw looks like ?? throw is part of the default parameter value.
  6. void M(string s is not null);
    1. Our concerns here are the same as 5.
  7. void M(checked string s);
    1. We like that checked already deals with exceptions, and it feels like the right word to use: when used with arithmetic, it ensures that users aren't violating the bounds of a type, which is very similar to parameter null checking. However, checked can already be applied to expressions, or even turned on project-wide, and we're not sure how we'd apply the null-checking feature in these locations: should all parameters be null-checked if the project-wide setting is on, for example? Or should a ! in a checked block be checked for null?
  8. void M(string s) where s is not null;
    1. This looks like a promising start for a full contracts feature, but not for a feature only doing null checking of parameters.

After the discussion leading to the above points, we felt that only two of the options had enough support to continue discussion: option 1, the current form, and option 3, the less shouty version of the current form.

We then turned our focus to question 2: do we still feel confident in this feature at all? As part of this, we also looked at the initial feedback we received on this feature by a number of channels: GitHub, social media, MVPs, conference audiences, internal reviewers, and the LDT itself. We do see a majority of positive reactions to the feature, but it isn't the large majority we normally like to see for C# features, particularly ones that are as broadly applicable as this feature will be, and even the LDT is split on the feature itself. While we think the preview provided us with valuable feedback and was worth pursuing, we ultimately decided that, between options 1, 3, or pulling the feature from C# 11 entirely, pulling the feature is the right move. We may revisit at a later date, if we ever want to pursue more generalized contracts, but for C# 11 this feature will removed.

Conclusion

Parameter null checking is removed from C# 11.

File-scoped types

https://github.com/dotnet/csharplang/issues/5529
https://github.com/dotnet/csharplang/issues/6011

This next change in design of this feature pares it back significantly, basically back to the original design, but with a couple of key differences:

  1. There is no private keyword here, which was a significant stumbling block in understanding of the feature and unintended feature creep.
  2. There are more heavy restrictions on how the feature can be used.

In particular, this version solves the immediate source-generator issues that the BCL is running into, while allowing us design room if we ever want to expand the feature in the future. We do need to validate that the restrictions around partial types and signatures will solve all the issues the BCL source-generators have, but we think it's a forward direction we can make progress on.

Conclusion

The updated proposal can move forward, and we should validate the restrictions on partial types will solve the scenarios in the BCL.