117 lines
2.4 KiB
Markdown
117 lines
2.4 KiB
Markdown
|
# C# Language Design Notes for Feb 20th, 2019
|
||
|
|
||
|
## Agenda
|
||
|
|
||
|
- Nullable Reference Types: Open LDM Issues https://github.com/dotnet/csharplang/issues/2201
|
||
|
|
||
|
## Discussion
|
||
|
|
||
|
There are variants of this scenario with `string!` and `string~`. The question is whether we should learn in both branches, or whether we should treat one branch as unreachable.
|
||
|
|
||
|
### 'Deliberate' Tests for Nullability
|
||
|
|
||
|
This is a continuation of the discussion from the [last meeting](LDM-2019-02-13.md).
|
||
|
|
||
|
Proposal: divide into "pure" and "not-pure" null checks. The "pure"
|
||
|
null checks will affect both branches, but the "not-pure" will only
|
||
|
affect one branch. Precisely: when a "pure" check is used, the
|
||
|
nullability state is split for both branches, while a non-pure check
|
||
|
does not have a "maybe-null" state after split.
|
||
|
|
||
|
Proposed deliberate checks:
|
||
|
|
||
|
1. `x == null`
|
||
|
|
||
|
2. `x != null`
|
||
|
|
||
|
3. `(Type)x == null`
|
||
|
|
||
|
4. `(Type)x != null`
|
||
|
|
||
|
5. `x is null`
|
||
|
|
||
|
6. `s is string` (when the type of `s` is `string`)
|
||
|
|
||
|
7. `s is string s2` (when the type of `s` is `string`)
|
||
|
|
||
|
8. `s is string _` (when the type of `s` is `string`)
|
||
|
|
||
|
|
||
|
Other checks:
|
||
|
|
||
|
1. `x is string`
|
||
|
|
||
|
2. `x is string s`
|
||
|
|
||
|
3. `x is C { Property = 3 }`
|
||
|
|
||
|
4. `TryGetValue` (`[NotNullWhenTrue]`)
|
||
|
|
||
|
5. `string.IsNullOrEmpty(s)` (`[NotNullWhenFalse]`)
|
||
|
|
||
|
6. `x?.ToString() != null`
|
||
|
|
||
|
Follow up question: What about `?.` and related operators (e.g., `??`)?
|
||
|
|
||
|
An example would be
|
||
|
|
||
|
```C#
|
||
|
void M(string s)
|
||
|
{
|
||
|
if (s?.ToString() == null)
|
||
|
{
|
||
|
// is `s` maybe null?
|
||
|
}
|
||
|
}
|
||
|
```
|
||
|
|
||
|
A corresponding rewrite would be:
|
||
|
|
||
|
```C#
|
||
|
void M(string s)
|
||
|
{
|
||
|
if (s == null || s.ToString() == null)
|
||
|
{
|
||
|
// s would be maybe-null after this point
|
||
|
}
|
||
|
}
|
||
|
```
|
||
|
|
||
|
**Conclusion**
|
||
|
|
||
|
Pure:
|
||
|
|
||
|
1. `x == null`
|
||
|
|
||
|
2. `x != null`
|
||
|
|
||
|
3. `(Type)x == null`
|
||
|
|
||
|
4. `(Type)x != null`
|
||
|
|
||
|
5. `x is null`
|
||
|
|
||
|
6. `s is string` (when the type of `s` is `string`)
|
||
|
|
||
|
|
||
|
All conditional access (`?.`, `??`) included
|
||
|
|
||
|
Not-Pure
|
||
|
|
||
|
1. `x is string`
|
||
|
|
||
|
2. `x is string s`
|
||
|
|
||
|
3. `x is C { Property = 3 }`
|
||
|
|
||
|
4. `TryGetValue` (`[NotNullWhenTrue]`)
|
||
|
|
||
|
5. `string.IsNullOrEmpty(s)` (`[NotNullWhenFalse]`)
|
||
|
|
||
|
7. `s is string s2` (when the type of `s` is `string`)
|
||
|
|
||
|
8. `s is string _` (when the type of `s` is `string`)
|
||
|
|
||
|
Switch statement/expression: switch statement treated as
|
||
|
essentially the equivalent of an `if/else` rewrite. No
|
||
|
decisions for the switch expression yet.
|