I\'ve a project on which I enabled the new Nullable reference type feature
enable
<
In the original implementation, foo
would have been inferred as a Foo
.
However, people complained that this got in the way of things like:
string? GetThing() => ...
var result = "";
if (condition)
{
result = GetThing();
}
If result
is inferred as a string
, then the result = GetThing()
line causes a warning: GetThing()
returns a string?
, and there's a warning if you try and assign a string?
to a string
.
The solution was to infer result
as a string?
, but the compiler knows that it's currently not null (its "flow state" is "NotNull").
This means that:
string? GetThing() => ...
var result = "";
// No warning, as the compiler knows that result isn't null
int l1 = result.Length;
if (condition)
{
result = GetThing();
}
// Warning: the compiler knows 'result' might have been re-assigned
int l2 = result.Length;
For other examples of the flow state at work, see things like:
string? result = GetString();
if (result == null)
throw new Exception();
// No warning: the compiler knows that result can't be null here: if it was,
// the exception above would have been thrown
int l1 = result.Length;
string? result = GetString();
// Warning: result might be null
int l1 = result.Length;
// No warning: the compiler knows that result can't be null here: if it was,
// the line above would have thrown
int l2 = result.Length;
string result = "hello";
if (result == null)
Console.WriteLine("NULL!");
// Warning: because we checked for null above, the compiler assumes that we
// know something that it doesn't, and so result might be null.
int l1 = result.Length;