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.
|