# C# Language Design Meeting for April 13th, 2022

## Agenda

- [Parameter null checking](#parameter-null-checking)
- [File-scoped types](#file-scoped-types)

## 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](LDM-2022-04-06.md#parameter-null-checking) 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.
