3.4 KiB
C# Language Design Notes for Oct 11, 2017
Warning: These are raw notes, and still need to be cleaned up. Read at your own peril!
Agenda
We looked at the design review feedback for nullable reference types.
Philosophy
Takeaways: Let unconstrained type parameters be its own special case; don't let it degrade the experience.
This is linting, make most existing code work, and don't shout at people too much.
Conclusion
agree, but let's consider a paranoid mode; "Xtreme". Could do that later.
Everybody who want the Xtreme mode would be happier with something than nothing. Should see what reaction is, and then dfecide whether to do it in-compiler, as analyzers or not at all.
Switches
Feedback: Don't have many switches. Just on or off.
Off would mean suppress the warnings. The syntax would still be allowed.
Conclusion
THis is a good philosophy. (We might allow Xtreme). We don't need to prototype the switch; it would always be on.
Dotted names
Feedback is we should track dotted names, and be very forgiving about what invalidates null state.
Invalidation: assigning to a prefix, or passing it by out or ref.
Conclusion
(Could go different with Xtreme mode)
Type narrowing
void M(string? n)
{
if (n == null) return;
var s = n; // string
var l = s.Length;
n = null; // ok
s = null; // ???
}
(Separate design discussion for IDE about what to show for n).
T[] MakeArray<T>(T v1, T v2)
{
return new T[] { v1, v2 };
}
void M(string? n)
{
if (n == null) return;
var a = MakeArray(n, n); // string[] or string?[] ?
var l = a[0].Length; // ???
}
T N<T>(ref T r, T t)
{
}
void M(string? n)
{
if (n == null) return;
var s = N(ref n, n);
}
This one is interesting because even though n goes in as an lvalue, the method cannot legally assign a null to it.
Conclusion
We want to start treating the values of nullable variables with nonnull state as nonnullable in type inference.
Dammit operator type narrowing
T[] MakeArray<T>(T v)
{
return new T[] { v };
}
void M(string? n)
{
var a = MakeArray(n!); // string[] ?
var l = a[0].Length; // ???
}
Null suppression:
List<string?> l = GetList()!; // returns List<string>
Conclusion
`! should keep its warning suppression, but also narrow the outermost type when it can, to match the new behavior when null-state is non-null.
There's hesitation because of the muddiness of using !
for two different things. But we don't have a better idea. Explicit casts are quite verbose. We may need to revisit later.
Dammit operator stickiness
Dammit operator lacks "stickiness" - you have to keep applying it (or introduce another local).
Idea is to maybe have some top-level "assertion" that would declare a thing not-null for the whole scope.
Other idea is to have s!
influence null state for flow analysis, staying "valid" for as long as a non-null state would have.
string? s = ...
if (s != null && s.Length == 5) ... // It flows here
M((s!, s); // why not here?
It would sort of make s!
mean the same as s = s!
.
There are also cases where you wouldn't want it to be sticky, e.g. when you are using !
to shut a specific unannotated API that is lacking a ?
.
Conclusion
We don't know what, if anything, to do here.
Array covariance
Conclusion
We'll think about this more.
Null warnings
Agree with feedback