Add raw notes for 3/21/2018
This commit is contained in:
parent
9cb067bb79
commit
e2739501f7
107
meetings/2018/LDM-2018-03-21.md
Normal file
107
meetings/2018/LDM-2018-03-21.md
Normal file
|
@ -0,0 +1,107 @@
|
|||
# C# Language Design Notes for Mar 21, 2018
|
||||
|
||||
***Warning: These are raw notes, and still need to be cleaned up. Read at your own peril!***
|
||||
|
||||
## Agenda
|
||||
|
||||
We discussed various open questions around nullable reference types
|
||||
|
||||
|
||||
# The null-forgiving operator
|
||||
|
||||
## Name
|
||||
|
||||
Null-acquiescing
|
||||
Null-forgiving
|
||||
Null-silencing
|
||||
Null-quieting
|
||||
Darnit
|
||||
|
||||
## What does it do?
|
||||
|
||||
Changes top-level nullability to not-null, as well as silencing warnings even on nested nullability
|
||||
|
||||
``` c#
|
||||
void M(string? ns, List<string?>? ln)
|
||||
{
|
||||
string s = ns!; // silence and change nullability
|
||||
var s2 = ns!; // silence and produce string
|
||||
ln = null;
|
||||
List<string>? l = ln!; // silence and change
|
||||
var l2 = ln!;
|
||||
// Idea 1
|
||||
l! // change nullability at the top level
|
||||
l<!> // idea: change nullability at the nested level
|
||||
// Idea 2
|
||||
(List<string>?!)ln; // I do a cast that should warn but ! silences it
|
||||
List<string>? l3 = (!)ln; // Shorthand
|
||||
}
|
||||
```
|
||||
|
||||
Should `!` only change top-level nullability, and not suppress nested diagnostics? Or the other way around? Is it a problem that it does both and "suppresses too much".
|
||||
|
||||
Since we made affordances for legacy code, the need for passing `null!` for instance is less: unannotated APIs already suppress warnings.
|
||||
|
||||
Scenarios for `!` now that legacy APIs aren't a scenario:
|
||||
|
||||
1. I'm in the middle of converting my own code; need them at the boundary
|
||||
2. The compiler can't figure it out, but I'm right
|
||||
|
||||
Great example of the latter:
|
||||
|
||||
``` c#
|
||||
List<string?> strings;
|
||||
var query = strings.Where(s => s != null).Select(s => s.Length); // What?? Why warning?
|
||||
```
|
||||
Here you can put the `!` in `s!.Length`, but what if you have
|
||||
|
||||
``` c#
|
||||
void M(IEnumerable<string> source) { ... }
|
||||
List<string?> strings;
|
||||
M(strings.Where(s => s != null)); // What?? Why warning?
|
||||
```
|
||||
|
||||
Here you need to suppress on the nested nullability, because you know better.
|
||||
|
||||
Currently you can say `!` at the end of the argument to set it right. Should that be a different syntax?
|
||||
|
||||
What's the problem with `!` doing both jobs?
|
||||
|
||||
``` c#
|
||||
void M(string? ns, List<string?>? ln)
|
||||
{
|
||||
// I happen to know that if ln is not null, it doesn't contain nulls
|
||||
List<string>? l = ln!;
|
||||
_ = l.Count; // warning?
|
||||
}
|
||||
```
|
||||
|
||||
Now `l.Length` is not warned on because `!` did "too much". We wanted it to silence warnings, but it also changed the null state.
|
||||
|
||||
The simplest fix with current semantics would be to cast to a nullable type:
|
||||
|
||||
``` c#
|
||||
List<string>? l = (List<string>?)ln!; // or
|
||||
var l = (List<string>?)ln!;
|
||||
```
|
||||
|
||||
Proposals:
|
||||
|
||||
1. Change null state and suppress 4
|
||||
2. Two syntaxes 5
|
||||
3. Only suppress warnings 1
|
||||
4. Only change null-state 0
|
||||
|
||||
Approachable and easy to use. They are all about telling the compiler to shut up when you know what you're doing.
|
||||
|
||||
For 3, the things we would make people do to change the null state would also be a hurdle.
|
||||
|
||||
If we separate it, one may be a temporary feature that will go away over time, once people have transitioned.
|
||||
|
||||
We're not going to settle this today. The prototype does "1+" which is even more lenient than 1.
|
||||
|
||||
|
||||
|
||||
# Special methods
|
||||
|
||||
# Hidden diagnostic
|
Loading…
Reference in a new issue