83 lines
1.7 KiB
Markdown
83 lines
1.7 KiB
Markdown
|
||
# C# Design Review Notes for Oct 31, 2018
|
||
|
||
This was a review with the full design team (including Anders) to see how the
|
||
whole release is shaping out.
|
||
|
||
## Discussion
|
||
|
||
### Nullable
|
||
|
||
#### Flow analysis to turn a non-nullable type to nullable
|
||
|
||
The question is whether flow analysis can cause types to become nullable if a
|
||
value of non-nullable type is compared to null.
|
||
|
||
```C#
|
||
void M(string x)
|
||
{
|
||
if (x == null)
|
||
{
|
||
// is x now treated as ‘string?’ here?
|
||
}
|
||
}
|
||
```
|
||
|
||
This is an issue that TypeScript has dealt with. There's some worry that most
|
||
of the warnings will be produced not at the place with the problem. We should
|
||
be careful that we're not going to annoy the user.
|
||
|
||
#### Flow analysis and refactoring
|
||
|
||
Flow analysis constrains refactoring because something may be tested null by
|
||
flow analysis, but if you pass to a new method, the flow analysis is lost. For
|
||
example:
|
||
|
||
```C#
|
||
class C
|
||
{
|
||
string? Prop1 { get; }
|
||
string? Prop2 { get; }
|
||
}
|
||
|
||
class C2
|
||
{
|
||
void M1(C c)
|
||
{
|
||
if (c.Prop1 != null && c.Prop2 != null)
|
||
{
|
||
M2(c);
|
||
}
|
||
}
|
||
|
||
void M2(C c)
|
||
{
|
||
// The null checking from M1 is lost here and M2 has to
|
||
// check again for null to avoid a warning
|
||
c.Prop1.Equals(...)
|
||
}
|
||
}
|
||
```
|
||
|
||
#### `!` on parameters
|
||
|
||
Very different behavior depending on where `!` appears -- maybe too many
|
||
meanings.
|
||
|
||
#### Treatment of lambdas
|
||
|
||
For
|
||
|
||
```C#
|
||
void M()
|
||
{
|
||
int? x = null;
|
||
Action a = () => x = 0;
|
||
a();
|
||
// What's the null state of `x` here?
|
||
}
|
||
```
|
||
|
||
Treating the delegate conversion as executing the method is unsafe, but
|
||
not doing so is conservative and will warn on valid checking. TypeScript
|
||
has also hit this and there's no easy answer. |